更新时间:2023-09-14 12:17:40
这就是反向引用的用途.只需用括号将要捕获的文本部分括起来即可.第一组括号以 $1 提供,第二组以 $2 提供,依此类推.
This is what backreferences are for. Just surround the section of text you want to capture with parentheses. The first set of parentheses are available in $1, the second in $2, and so on.
s/(\s[0-9]\s[0-9]{3})/$1I/
使用 Perl 5.10,我们获得了命名捕获,所以你可以说
With Perl 5.10 we gained named captures, so you can say
s/(?<bodytext>\s[0-9]\s[0-9]{3})/$+{bodytext}I/
和
>
之间的东西是名字.名称成为 %+
变量中的键,值是捕获的文本.
The stuff inbetween <
and >
is the name. Names become keys in the %+
variable and the values are the captured text.
另一种解决方案是使用 零宽度正向后视
Another solution is to use a zero-width positive look-behinds
s/(?<=\s[0-9]\s[0-9]{3})/I/
或其,Perl 5.10 的新内容,简写 \K
or its, new to Perl 5.10, shorthand \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
如果你使用双引号,$1 会在 Perl 看到它之前被 shell 插入.如果你认为应该工作的东西有问题,那么看看 Perl 看到的东西可能是个好主意.你可以用 B::Deparse:
If you use double quotes the $1 is interpolated by the shell before Perl ever sees it. If you have problems with something you think should work, it may be a good idea to take a look at what Perl is seeing. You can do this with 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
缺失.让我们用单引号再试一次:
From this we can see that $1
is missing. Lets try again with single quotes:
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