Perl 字符串替换不起作用的 $1 和 $2



当我使用之前定义的 $1 和 $2 时,搜索和替换不起作用。

当我将其存储在新变量中时,它可以工作。

无法按预期工作。

perl -e'
   my $name = "start middle end";
   my $rep = "";
   my $orig = "";
   if ($name =~ /sta(.*?)sw+s(.*)/) {
      $orig = $1;
      $rep = $2;
      $name =~ s/$1/$2/;
      print "$namen";
   }
'
sta middle end

是因为 1 美元和 2 美元在新$name中被替换了吗 =~ 我在做?

按预期工作。

perl -e'
   my $name = "start middle end";
   my $rep = "";
   my $orig = "";
   if ($name =~ /sta(.*?)sw+s(.*)/) {
      $orig = $1;
      $rep = $2;
      $name =~ s/$orig/${rep}/;
      print "$namen";
   }
'
staend middle end

有没有更好的班轮来做到这一点?我不想定义新变量。

通过在 s///运算符的第一部分中运行匹配来重置捕获变量,以供替换使用。列表上下文中的 m//运算符将返回捕获的值,以便您可以轻松地在其中分配它们。此外,如果您的搜索字符串不是正则表达式,您可能希望使用 \Q (quotemeta(。

perl -e'
   my $name = "start middle end";
   if (my ($orig, $rep) = $name =~ /sta(.*?)sw+s(.*)/) {
      $name =~ s/Q$orig/$rep/;
      print "$namen";
   }
'
sta middle end

是的,新的成功正则表达式匹配取代了$1$2

您可以完全避免全局变量,如下所示:

perl -e'
   my $name = "start middle end";
   if ( my ($orig, $rep) = $name =~ /sta(.*?)sw+s(.*)/ ) {
      $name =~ s/Q$orig/$rep/;
      CORE::say $name;
   }
'

更好的是,您可以避免进行以下两场比赛:

perl -e'
   my $name = "start middle end";
   if ( $name =~ s/staK.*?(?=sw+s(.*))/$1/ ) {
      CORE::say $name;
   }
'

但是,我会使用以下方法:

perl -e'
   my $name = "start middle end";
   if ( (my ($prefix, $suffix, $foo) = $name =~ /^(.*?sta).*?(sw+s(.*))/ ) {
      CORE::say "$prefix$foo$suffix";
   }
'

请注意,您的代码遭受了代码注入错误,我使用 quotemeta 修复了该错误(如Q(。

在这里,以防万一,我们会有意想不到的额外空格,我们也可以尝试这个表达式:

(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 "$namen";
    '

输出

staend middle end

请在此处观看演示

替换部分中的$2是指来自同一替换的图案部分中的捕获组。因此,您只需要一个变量即可记住 $2。

perl -lwe '$_ = "start middle end" ; if (/sta(.*?)sw+s(.*)/) {my $rep = $2; s/$1/$rep/; print}'
staend middle end

您可以通过使用最后一个匹配开始和结束全局数组@-@+并只执行子字符串替换来避免其他变量:

my $name = "start middle end";
if ($name =~ /sta(.*?)sw+s(.*)/) {
    substr($name, $-[1], $+[1]-$-[1], $2);
    print "$namen";
}

请参阅perldoc perlvar@-条目

正则表达式捕获变量根据代码
表现出奇怪的行为流,函数调用和其他东西。
要完全解释和理解这一点,需要几页
的解释。

至于现在,避免整个混乱,只使用一个正则表达式

 perl -e'
    my $name = "start middle end";
    $name =~ s/^(sta)(.*?)(sw+s)(.*)/$1$4$3$4/;
    print "$namen";
 '

最新更新