Perl 一行:替换中的捕获组被解释为八进制

问题描述 投票:0回答:2

假设我有一个包含文本

foo_bar_baz
的文件,并且我想将其替换为
foo_bar_var
(其中
var
是 bash 变量的值):

第一次尝试:

 #!/bin/bash
 $ key=1234
 $ echo "foo_bar_baz" > testfile
 $ perl -pi -e "s/(foo_)(bar_).*/\1\2 $key/" testfile
 $ cat testfile
 foo_bar_ 1234

所以,我只需要去掉

1234
之前的空格即可。显而易见的答案是

 $ perl -pi -e "s/(foo_)(bar_).*/\1\2$key/" testfile

...但这行不通。替换中包含八进制字符

\212
。我该如何解决?八进制问题简要介绍了here,但我似乎错过了答案。该文档指出“只有在其前面至少有 10 个左括号时,Perl 才会通过解释为反向引用来解决这种歧义”,但这里显然不是这种情况。此外,使用
\g2
\g{2}
并不能解决问题。

我使用的是 Perl 5.34.0,bash 5.1.16。

编辑

澄清这是 bash 脚本中的一行,所以我不能使用单引号代替双引号,并且我不能用

$
替换,因为这些是 bash 变量。

regex bash perl
2个回答
4
投票

替换文本应使用

$1
代替
\1
来表示捕获组的内容。与任何其他参数扩展一样,您可以使用
{...}
分隔参数名称。

perl -pi -e 's/(foo_)(bar_).*/$1${2}1234/' testfile

(请注意使用单引号来简化对

$1
$2
的转义,以避免在 Perl 看到要执行的脚本之前对每个内容进行 shell 插值。)


0
投票

经过大量随机输入后,我想我找到了一个“答案”,但我不喜欢它。问题中的原始代码有效 if 您可以保证要替换的变量的第一个字符不是数字(因此

key=abcd
有效,但
key=1bcd
无效)。

如果您事先不知道变量的第一个字符是什么,那么您必须导出并读取变量:

#!/bin/bash
echo "foo_bar_baz" > testfile
export key=1235
perl -pi -e 's/(foo_)(bar_).*/$1$2$ENV{key}/' testfile
cat testfile

这似乎与here的文档完全相反,因为这里只有2个捕获组,所以不存在歧义的可能性(

\21234
不可能是一个捕获组)。

这让我觉得在 bash 脚本中使用 Perl 语句进行替换并不是一个好主意。我已经发现我的一个旧脚本没有用数字进行测试并且失败了。将来,我想我将使用 bash-native 替换。

© www.soinside.com 2019 - 2024. All rights reserved.