我正在尝试替换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命令行中重现类似的行为。)
答案 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