我正在尝试替换 VMS 上文本文件中的特定行。通常,这是使用 Perl 进行的简单一行操作。但当替换面是包含 VMS 路径的符号时,我遇到了问题。这是文件和我尝试过的内容:

file1.txt的内容:

foo
bar
baz
quux

尝试替换第三行:

$ mysub = "disk$data1:[path.to]file.txt"
$ perl -pe "s/baz/''mysub'/" file1.txt

产生以下输出:

foo
bar
disk:[path.to]file.txt
quux

看来 Perl 过于渴望并取代了 $data1 路径的一部分包含不存在的变量的内容(即什么都没有)。使用调试器运行证实了这一点。我没有供应 /e, ,所以我认为 Perl 应该按原样替换文本。有没有办法让 Perl 做到这一点?

(另请注意,我可以在 Linux 命令行中重现类似的行为。)

有帮助吗?

解决方案

通过正确的引号和双引号的组合,您可以到达那里:

我们创建“字符串”+“替换符号”+“字符串”的紧密串联。两个双引号字符串包含用于替换的单引号。做作...但它有效。

$ perl -pe "s'baz'"'mysub'"'" file1.txt

这是DCL级别的解决方案。

对于 Perl 解决方案,请使用 q() 非内插字符串的运算符并执行它。使用简单的 DCL 替换将符号填充到括号中。这是我最喜欢的,因为它(几乎)对我来说很有意义,并且不会与引号混淆。

$ perl -pe "s/baz/q(''mysub')/e" file1.txt

其他提示

作为 鲁阿赫 在阅读我的评论时发现,perl插值的问题可以通过访问来解决 %ENV hash,而不是使用 shell 变量:

perl -pwe "s/baz/$ENV{mysub}/" file1.txt

添加 -w 因为我不相信不使用 warnings 即使是单行。

几十年来甚至没有见过 VMS 系统,但是......逃离你的印记?

$ mysub = "disk\$data1:[path.to]file.txt"

或者可能

$ mysub = "disk\\$data1:[path.to]file.txt"

?

为了 sh 或衍生品,我会用

perl -pe'BEGIN { $r = shift(@ARGV) } s/baz/$r/' "$mysub" file1.txt

否则,你必须以某种方式隐藏 mysub 转换为 Perl 字符串文字。那会更复杂。找到适合您的 shell 的等效项。

OP编辑:

是的,这有效。VMS 等效为

perl -pe "BEGIN { $r = shift(@ARGV) } s/baz/$r/" 'mysub' file1.txt

你必须逃离 $\$. 。否则 Perl 会看到变量引用并替换字符串 $data1 与内容 $data1 在评估正则表达式之前。因为你没有定义 $data1 当然,它是空的。

您可以使用以下代码:

$ mysub='disk\$data1:[path.to]file.txt'
$ perl -pe 's/baz/'$mysub'/' FILE
foo
bar
disk$data1:[path.to]file.txt
quux

您可以尝试使用逻辑名称而不是 DCL 符号:

$ define mysub "disk$data1:[path.to]file.txt"
$ $ perl -pe "s/baz/mysub/" file1.txt

使用 sed。

sed 不会尝试插值 $data1 作为一个变量,所以你应该得到你想要的。

$ sed -e "s/baz/''mysub'/" file1.txt
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top