[英]How can I disable variable interpolation with the Perl substitution operator?
I'm trying to replace a particular line in a text file on VMS. 我正在尝试替换VMS上的文本文件中的特定行。 Normally, this is a simple one-liner with Perl.
通常,这是一个简单的Perl单线程。 But I ran into a problem when the replacement side was a symbol containing a VMS path.
但是当替换方是包含VMS路径的符号时,我遇到了问题。 Here is the file and what I tried:
这是文件和我尝试的内容:
Contents of file1.txt: file1.txt的内容:
foo
bar
baz
quux
Attempt to substitute 3rd line: 尝试替换第3行:
$ mysub = "disk$data1:[path.to]file.txt"
$ perl -pe "s/baz/''mysub'/" file1.txt
Yields the following output: 产生以下输出:
foo
bar
disk:[path.to]file.txt
quux
It looks like Perl was overeager and replaced the $data1
part of the path with the contents of a non-existent variable (ie, nothing). 看起来Perl过于苛刻,用一个不存在的变量的内容替换路径的
$data1
部分(即什么都没有)。 Running with the debugger confirmed that. 运行调试器确认了这一点。 I didn't supply
/e
, so I thought Perl should just replace the text as-is. 我没有提供
/e
,所以我认为Perl应该直接替换文本。 Is there a way to get Perl to do that? 有没有办法让Perl这样做?
(Also note that I can reproduce similar behavior at the linux command line.) (另请注意,我可以在linux命令行中重现类似的行为。)
As ruakh discovered when reading my comment, the problem of perl interpolation can be solved by accessing the %ENV
hash, rather than using a shell variable: 正如Ruakh在阅读我的评论时发现的那样,perl插值问题可以通过访问
%ENV
哈希来解决,而不是使用shell变量:
perl -pwe "s/baz/$ENV{mysub}/" file1.txt
Added -w
because I do not believe in not using warnings
even in one-liners. 添加
-w
因为我不相信即使在单行中也不使用warnings
。
With just the right mix of quotes and double quotes you can get there: 只需正确混合引号和双引号,您就可以到达:
We create a tight concatenation of "string" + 'substitute symbol' + "string". 我们创建了“string”+“替换符号”+“string”的紧密连接。 The two double quoted strings contain single quotes for the substitute.
两个双引号字符串包含替换的单引号。 Contrived... but it works.
Contrived ......但它确实有效。
$ perl -pe "s'baz'"'mysub'"'" file1.txt
That's a DCL level solution. 这是一个DCL级别的解决方案。
For a Perl solution, use the q()
operator for a non-interpolated string and execute that. 对于Perl解决方案,使用
q()
运算符作为非插值字符串并执行它。 Stuff the symbol into the parens using simple DCL substitution. 使用简单的DCL替换将符号填入parens。 This is my favorite because it (almost) makes sense to me and does not get too confusing with quotes.
这是我的最爱,因为它(几乎)对我有意义,并且不会引起混淆。
$ perl -pe "s/baz/q(''mysub')/e" file1.txt
Haven't even seen a VMS system in decades, but ... escape your sigil? 几十年来甚至没有见过VMS系统,但是......逃避你的印记?
$ mysub = "disk\$data1:[path.to]file.txt"
or maybe 或者可能
$ mysub = "disk\\$data1:[path.to]file.txt"
? ?
For sh
or a derivative, I'd use 对于
sh
或衍生物,我会使用
perl -pe'BEGIN { $r = shift(@ARGV) } s/baz/$r/' "$mysub" file1.txt
Otherwise, you have to somehow covert the value of mysub
into a Perl string literal. 否则,你必须以某种方式将
mysub
的值转换为Perl字符串文字。 That would be more complicated. 那会更复杂。 Find the equivalent for your shell.
找到你的shell的等价物。
Edit by OP: 由OP编辑:
Yes, this works. 是的,这很有效。 The VMS equivalent is
VMS等价物是
perl -pe "BEGIN { $r = shift(@ARGV) } s/baz/$r/" 'mysub' file1.txt
Use sed. 使用sed。
Sed won't try to interpolate $data1
as a variable, so you should get what you want. Sed不会尝试将
$data1
插入为变量,因此您应该得到您想要的。
$ sed -e "s/baz/''mysub'/" file1.txt
You have to escape the $
with \\$
. 你必须逃离
$
用\\$
。 Otherwise Perl sees a variable reference and replaces the string $data1
with the content of $data1
before the regular expression is evaluated. 否则,Perl中看到一个变量引用,并替换字符串
$data1
与内容$data1
正则表达式求值之前。 As you didn't define $data1
it is, of course, empty. 由于你没有定义
$data1
它当然是空的。
You can use the following code : 您可以使用以下代码:
$ mysub='disk\$data1:[path.to]file.txt'
$ perl -pe 's/baz/'$mysub'/' FILE
foo
bar
disk$data1:[path.to]file.txt
quux
You could try using a logical name instead of a DCL symbol: 您可以尝试使用逻辑名称而不是DCL符号:
$ define mysub "disk$data1:[path.to]file.txt"
$ $ perl -pe "s/baz/mysub/" file1.txt
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.