如何使用Perl替换运算符禁用变量插值?

时间:2012-10-01 18:02:28

标签: regex perl vms

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

file1.txt的内容:

foo
bar
baz
quux

尝试替换第3行:

$ 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命令行中重现类似的行为。)

8 个答案:

答案 0 :(得分:4)

在阅读我的评论时发现ruakh,可以通过访问%ENV哈希来解决perl插值问题,而不是使用shell变量:

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

添加了-w,因为我不相信即使在单行中也不使用warnings

答案 1 :(得分:4)

只需正确混合引号和双引号即可到达:

我们创建了" string"的紧密连接。 +'替换符号' +" string"。 两个双引号字符串包含替换的单引号。 Contrived ......但它确实有效。

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

这是一个DCL级解决方案。

对于Perl解决方案,使用q()运算符作为非插值字符串并执行它。 使用简单的DCL替换将符号填入parens。 这是我的最爱,因为它(几乎)对我有意义,并且不会引起混淆。

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

答案 2 :(得分:1)

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

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

或者

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

答案 3 :(得分:1)

对于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

答案 4 :(得分:0)

使用sed。

Sed不会尝试将$data1插入为变量,所以你应该得到你想要的。

$ sed -e "s/baz/''mysub'/" file1.txt

答案 5 :(得分:0)

您必须使用$转义\$。否则Perl会看到一个变量引用,并在评估正则表达式之前用$data1的内容替换字符串$data1。由于你没有定义$data1,它当然是空的。

答案 6 :(得分:0)

您可以使用以下代码:

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

答案 7 :(得分:0)

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

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