前置模式匹配后,Perl的substitute无法工作

6

我有一个奇怪的问题,就是在先前进行模式匹配之后,替代运算符s///不起作用。例如:

use strict; 
use warnings; 

my $var = "var"; 
$var =~ s||/|g; 

print "$var\n";

输出结果为:/v/a/r/
但在这种情况下,……
use strict; 
use warnings; 

my $a = "test"; 

if ($a =~ /te/) { 

    my $var = "var"; 
    $var =~ s||/|g; 

    print "$var\n"; 
}

输出结果是:var,而应该与之前的结果相同。这里发生了什么?我该如何修复它?
1个回答

5

perlop 对于 空模式“//” 有这样的说明:

如果 PATTERN 评估为空字符串,则使用最后一个已经匹配成功的正则表达式。在这种情况下,只有空模式上的 g 和 c 标志得到保留; 其他标志将从原始模式中获取。如果之前没有匹配成功过,那么它将(悄悄地)充当真正的空模式(总是匹配)。

因此,您的第一个案例对空字符串进行了替换,因为之前没有任何模式匹配,而第二个案例在 test 中成功匹配了 te ,因此在 var 中替换了每个 te,所以没有效果。

以下是该程序的演示:

use strict;
use warnings;

my $str = 'a/b/c';

if ($str =~ m{/}) {
  $str =~ s//x/g;
}

print $str;

输出

axbxc

唯一的例外是在“split”命令中的模式,如果您指定了空模式,则始终匹配一个空模式。

为了解决这个问题,如果您 真的 想匹配每个字符前后的点,请使用/x修饰符来使用无意义的空格作为您的模式,像这样:

use strict; 
use warnings; 

my $var_a = 'test'; 

if ($var_a =~ /te/) { 

    my $var_b = 'var'; 
    $var_b =~ s| |/|gx; 

    print "$var_b\n"; 
}

输出

/v/a/r/

非常感谢,我明白了 :-) (那个问题让我头疼 :D,还有感谢您的编辑)。 - user2676847

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接