题
我正在尝试替换 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