如何匹配Perl中的行首或字符?

时间:2016-12-16 12:36:50

标签: regex perl

例如,这没关系:

my $str = 'I am $name. \$escape';
$str =~ s/[^\\]\K\$([a-z]+)/Bob/g;
print $str; # 'I am Bob. \$escape';

但以下不是我的预期。

my $str = '$name';
$str =~ s/[^\\]\K\$([a-z]+)/Bob/g;
print $str; # '$name';

我该如何纠正?

2 个答案:

答案 0 :(得分:0)

  

如何在Perl中匹配行的开头或字符

字符类中的抑扬符失去了字符串开始锚点的含义。您需要使用非捕获组来代替字符类:

$str =~ s/(?:^|\\)\K\$([a-z]+)/Bob/g;
          ^^^^^^^^

(?:^|\\)会在字符串开头处声明位置,或者匹配\

对于那些只在$符号未转义时匹配才能理解问题的人,解决方案将是

$str =~ s/(?<!\\)(?:\\\\)*\K\$([a-z]+)/Bob/g;

此处,如果(?<!\\)前面带有$符号且\会消耗任何转义反斜杠,则(?:\\\\)*零宽度断言会导致匹配失败。如果存在)$之前\K匹配重置运算符将从匹配值中丢弃所有这些反斜杠。

答案 1 :(得分:0)

如果您的目标是匹配未通过反斜杠转义的$,则可以将模式更改为:

(?<!\\)(?:\\{2})*\K\$([a-z]+)

这样您就不必使用交替,因为负向后观匹配一个前面没有反斜杠的位置(包括字符串的开头)。

此外,当(?:\\{2})*之前的反斜杠本身使用其他反斜杠进行转义时,$可以防止错过。例如:\\$name