在使用Perl进行搜索和替换期间,如何添加而不是替换文本?

时间:2009-06-01 04:16:44

标签: regex perl

我正在尝试使用Perl中的正则表达式进行搜索和替换。

我要搜索的文字是:

<space>Number<space>NumberNumberNumber

我希望将其替换为:

<space>Number<space>NumberNumberNumberI

我有以下正则表达式,用于查找字符串:

\s[0-9]\s[0-9[0-9][0-9] 

但是如何更换字符串呢?基本上我只是想在最后附加一个“我”。

我正在使用:

perl -pi -e "s/\s[0-9]\s[0-9][0-9][0-9]/I/;" testFile 

但是这取代了整个事情而不是追加它。

2 个答案:

答案 0 :(得分:9)

这是后面的参考。只需用括号括起要捕获的文本部分。第一组括号以1美元计算,第二组以2美元计算,依此类推。

s/(\s[0-9]\s[0-9]{3})/$1I/

使用Perl 5.10我们获得了named captures,所以你可以说

s/(?<bodytext>\s[0-9]\s[0-9]{3})/$+{bodytext}I/

<>之间的内容是名称。名称成为%+变量中的键,值是捕获的文本。

另一种解决方案是使用zero-width positive look-behinds

s/(?<=\s[0-9]\s[0-9]{3})/I/

或者它是Perl 5.10的新手,简写\K

s/\s[0-9]\s[0-9]{3}\K/I/

尝试

perl -pi -e 's/(\s[0-9]\s[0-9][0-9][0-9])/$1I/' filename

如果你使用双引号,那么在Perl看到它之前,shell会内插$ 1。如果你认为应该有问题,那么看看Perl看到的东西可能是个好主意。您可以使用B::Deparse执行此操作:

perl -MO=Deparse -pi -e "s/(\s[0-9]\s[0-9][0-9][0-9])/$1I/" filename

这将产生以下输出。

BEGIN { $^I = ""; }
LINE: while (defined($_ = <ARGV>)) {
    s/(\s[0-9]\s[0-9][0-9][0-9])/I/;
}
continue {
    print $_;
}
-e syntax OK

从中我们可以看到$1缺失。让我们再试一次单引号:

perl -MO=Deparse -pi -e 's/(\s[0-9]\s[0-9][0-9][0-9])/$1I/' filename
BEGIN { $^I = ""; }
LINE: while (defined($_ = <ARGV>)) {
    s/(\s[0-9]\s[0-9][0-9][0-9])/$1I/;
}
continue {
    print $_;
}
-e syntax OK

一旦逃脱:

perl -MO=Deparse -pi -e "s/(\s[0-9]\s[0-9][0-9][0-9])/\$1I/" filename
BEGIN { $^I = ""; }
LINE: while (defined($_ = <ARGV>)) {
    s/(\s[0-9]\s[0-9][0-9][0-9])/$1I/;
}
continue {
    print $_;
}
-e syntax OK

答案 1 :(得分:0)

2009年答案的较短版本 - 您可以使用 零宽度正面观察断言 (?<=pattern)\K来在比赛结束后插入一些内容:

%echo "test" | perl -p -e "s/(?<=test)/ing/"
testing
%echo "test" | perl -p -e "s/test\K/ing/"
testing
%

或者,要在匹配前插入内容,您可以使用 零宽度正向前瞻断言 (?=pattern)

%echo "test" | perl -p -e "s/(?=test)/#/"
#test
%

参考: