5

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

4

8 回答 8

4

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

我们创建了“字符串”+“替代符号”+“字符串”的紧密连接。两个双引号字符串包含替换的单引号。做作......但它的工作原理。

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

这是一个 DCL 级别的解决方案。

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

$ perl -pe "s/baz/q(''mysub')/e" file1.txt
于 2012-10-01T23:06:03.550 回答
4

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

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

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

于 2012-10-01T18:40:24.980 回答
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
于 2012-10-01T18:18:02.907 回答
1

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

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

或者可能

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

?

于 2012-10-01T18:10:10.503 回答
0

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

$ define mysub "disk$data1:[path.to]file.txt"
$ $ perl -pe "s/baz/mysub/" file1.txt
于 2012-10-24T16:27:06.840 回答
0

你必须逃避$with \$。否则 Perl 看到一个变量引用,并在计算正则表达式之前将字符串替换为$data1的内容。$data1因为你没有定义$data1它当然是空的。

于 2012-10-01T18:06:44.753 回答
0

您可以使用以下代码:

$ mysub='disk\$data1:[path.to]file.txt'
$ perl -pe 's/baz/'$mysub'/' FILE
foo
bar
disk$data1:[path.to]file.txt
quux
于 2012-10-01T18:12:33.280 回答
-1

使用 sed。

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

$ sed -e "s/baz/''mysub'/" file1.txt
于 2012-10-01T18:02:28.033 回答