我正在尝试使用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
但是这取代了整个事情而不是追加它。
答案 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
%
参考: