当我使用前面定义的$ 1和$ 2时,搜索和替换不起作用。
当我将其存储在新变量中时,它将起作用。
不能按预期工作。
perl -e'
my $name = "start middle end";
my $rep = "";
my $orig = "";
if ($name =~ /sta(.*?)\s\w+\s(.*)/) {
$orig = $1;
$rep = $2;
$name =~ s/$1/$2/;
print "$name\n";
}
'
sta middle end
是因为$ 1和$ 2被替换为新的$ name =〜我在做什么吗?
按预期工作。
perl -e'
my $name = "start middle end";
my $rep = "";
my $orig = "";
if ($name =~ /sta(.*?)\s\w+\s(.*)/) {
$orig = $1;
$rep = $2;
$name =~ s/$orig/${rep}/;
print "$name\n";
}
'
staend middle end
是否有更好的班轮来做到这一点?我不想定义新变量。
答案 0 :(得分:4)
是的,新的成功正则表达式匹配替换了$1
和$2
。
您可以完全避免全局变量,如下所示:
perl -e'
my $name = "start middle end";
if ( my ($orig, $rep) = $name =~ /sta(.*?)\s\w+\s(.*)/ ) {
$name =~ s/\Q$orig/$rep/;
CORE::say $name;
}
'
更好的是,您可以避免进行以下两次匹配:
perl -e'
my $name = "start middle end";
if ( $name =~ s/sta\K.*?(?=\s\w+\s(.*))/$1/ ) {
CORE::say $name;
}
'
但是,我将使用以下内容:
perl -e'
my $name = "start middle end";
if ( (my ($prefix, $suffix, $foo) = $name =~ /^(.*?sta).*?(\s\w+\s(.*))/ ) {
CORE::say "$prefix$foo$suffix";
}
'
请注意,您的代码遇到了code injection错误,我已使用quotemeta
(如\Q
)对其进行了修复。
答案 1 :(得分:2)
通过在s ///运算符的第一部分中运行匹配项来重置捕获变量,以供替换使用。列表上下文中的m //运算符将返回捕获的值,因此您可以在此处轻松分配它们。另外,如果您的搜索字符串不是正则表达式,则可能要使用\ Q(quotemeta)。
perl -e'
my $name = "start middle end";
if (my ($orig, $rep) = $name =~ /sta(.*?)\s\w+\s(.*)/) {
$name =~ s/\Q$orig/$rep/;
print "$name\n";
}
'
sta middle end
答案 2 :(得分:1)
在这里,以防万一,我们会有意外的多余空间,我们也可以尝试以下表达式:
(sta)([a-z]*)\s+(\w+)\s+(.+)
这只是另一种选择。
perl -e'
my $name = "start middle end";
$name =~ s/(sta)([a-z]*)\s+(\w+)\s+(.+)/$1$4 $3 $4/;
print "$name\n";
'
staend middle end
答案 3 :(得分:0)
$2
指的是同一替换的图案部分中的捕获组。因此,您只需要一个变量即可记住$ 2。
perl -lwe '$_ = "start middle end" ; if (/sta(.*?)\s\w+\s(.*)/) {my $rep = $2; s/$1/$rep/; print}'
staend middle end
答案 4 :(得分:0)
您可以通过使用最后一个匹配的开始和结束全局数组@-
和@+
并仅执行子字符串替换来避免其他变量:
my $name = "start middle end";
if ($name =~ /sta(.*?)\s\w+\s(.*)/) {
substr($name, $-[1], $+[1]-$-[1], $2);
print "$name\n";
}
在perldoc perlvar
中查看@-
的条目
答案 5 :(得分:0)
regex捕获变量根据代码表现出奇怪的行为
流,函数调用和其他内容。
要对此进行全面的解释和说明,需要几页
的解释。
就目前而言,避免整个混乱,只需使用一个正则表达式
perl -e'
my $name = "start middle end";
$name =~ s/^(sta)(.*?)(\s\w+\s)(.*)/$1$4$3$4/;
print "$name\n";
'