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
,所以都是一样的。但是考虑到那些以这种方式理解问题的人,我在下面的(已经接受的)答案中添加了一个更新。