在perl v5.22.0中使用这个简单的例子:
my $data = "foobar\n";
$data =~ s/(?<!bar)(\s*)$/qux$1/;
print $data;
打印:
foobar
qux
但我不希望$data
改变。我也尝试了一些早期版本的perl 5.x,结果相同。
相反,我希望这个字符串使用相同的正则表达式来替换它,但它并没有:
my $data = "foobaz\n";
$data =~ s/(?<!bar)(\s*)$/qux$1/;
print $data;
我不明白为什么会这样。在任何一个星号都应该是贪婪的。我认为$1
将\n
使得负面后卫组与第一个示例中的bar
和第二个示例中的baz
进行比较。当我使用perl时Regex101说:
量词:*在零和无限次之间,尽可能多次,根据需要回馈。
所以在这种情况下会发生什么呢?它会回馈负面的后卫吗?
正如标题所说的那样,真正的问题是我想要阻止后卫吞下第二组。不幸的是,它不是一个字母,只是为了让它更容易理解。同样在perl中,我对负面观察能力有所限制,例如&#34;在正则表达式&#34;中没有实现可变长度观察。如果可能,我想要一个与perl 5.8兼容的答案。感谢
答案 0 :(得分:2)
它确实匹配最后一个位置,在位置为\n
之前,在$
之后,现在看起来是你的正则表达式:
(?<!bar)(\s*)$
在位置不是bar
之前:匹配
位置为$
后,匹配(\s*)$
答案 1 :(得分:2)
我想你想要
$data =~ s/(?<!bar)(?<!\s)(\s*)$/qux$1/;
以下版本将与5.8一起使用,我认为它实际上更快(因为它跳转到字符串的末尾并回溯,而不是在每个位置检查两个看后面):
$data =~ s/
^
(
(?:
.*
(?: [^r\s]
| [^a] r
| [^b] ar
)
)?
)
( \s* )
\z
/${1}qux$2/sx;
(可以使用$
代替\z
;它只是一种微优化。)
如果没有m
标记,$
等同于(?:\n?\z)
,它表示它匹配字符串末尾和字符串末尾的换行符。这意味着$
有两个匹配foobar␊
foobar␊ (There's a LF at position 6 in
01234567 case your font can't show it.)
^^
(?<!bar)
阻止第一个位置被考虑,但它允许第二个位置。
(?<!bar)(\s*)$
匹配位置7的0个字符,因为
(?<=bar)
匹配位置7的0个字符。(\s*)
匹配位置7的0个字符。$
匹配位置7的0个字符。这是唯一可能的匹配,所以贪婪是无关紧要的。