例如,这没关系:
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';
我该如何纠正?
答案 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