Regex 在Perl中,如何匹配行首或字符?
例如,这是确定的:Regex 在Perl中,如何匹配行首或字符?,regex,perl,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'; 我怎样才能纠正这个问题 在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';
我怎样才能纠正这个问题
在Perl中,如何匹配行首或字符
字符类中的扬抑符失去了字符串锚点开头的含义。您需要使用非捕获组,而不是字符类:
$str =~ s/(?:^|\\)\K\$([a-z]+)/Bob/g;
^^^^^^^^
此(?:^ | \\)
将在字符串开始处声明位置,或与\
匹配
对于那些仅当$
符号未转义时才将问题理解为匹配的人,解决方案将是
$str =~ s/(?<!\\)(?:\\\\)*\K\$([a-z]+)/Bob/g;
$str=~s/(?
在这里,(?零宽度断言是一个负查找,如果$
前面有\
符号,则匹配失败,(?:\\\\)*
将使用任何转义反斜杠(如果存在)在$
之前,而\K
匹配重置运算符将放弃匹配值中的所有这些反斜杠。如果您的目标是匹配未通过反斜杠转义的$
,则可以将模式更改为:
(?<!\\)(?:\\{2})*\K\$([a-z]+)
(?
这样,您就不必使用替换,因为负数lookback匹配的位置前面没有反斜杠(包括字符串的开头)
此外,(?:\{2})*
防止在$
之前的反斜杠本身用其他反斜杠转义时漏掉大小写。例如:\\$name
如果字符串是\$name
,将正则表达式更改为(?:^\\\\\\\\]\K\$([a-z]+)
@shawnhcorey:不,在$
之前必须有字符串开头或\
字符。您建议在$
之前使用字符串开头和\
以外的任何字符。最初的问题是使用字符类而不是分组构造,我在下面的回答中解决了这个问题。@WiktorStribi\380ew:你应该再读一遍这个问题(特别是第一个“ok”的例子)。我认为“character”这个词在标题中不代表反斜杠,而是代表一个不是反斜杠的字符。@casimirithippolyte:即使如此,标题与OP尝试的内容不一致,也没有什么区别:重点是使用分组结构。或者在正向后视中交替使用,但是由于使用了\K
,所以都是一样的。但是考虑到那些以这种方式理解问题的人,我在下面的(已经接受的)答案中添加了一个更新。