Ren*_*ger 7 regex perl negative-lookahead regex-lookarounds
如果测试的字符串后跟任意数量的空格(零包括)然后没有跟随,我有(我相信的)负向前瞻断言 <@> *(?!QQQ),我期望匹配.<@>QQQ
但是,如果测试的字符串是<@> QQQ正则表达式匹配.
我不明白为什么会出现这种情况,并希望对此事有任何帮助.
这是一个测试脚本
use warnings;
use strict;
my @strings = ('something <@> QQQ',
'something <@> RRR',
'something <@>QQQ' ,
'something <@>RRR' );
print "$_\n" for map {$_ . " --> " . rep($_) } (@strings);
sub rep {
my $string = shift;
$string =~ s,<@> *(?!QQQ),at w/o ,;
$string =~ s,<@> *QQQ,at w/ QQQ,;
return $string;
}
Run Code Online (Sandbox Code Playgroud)
这打印
something <@> QQQ --> something at w/o QQQ
something <@> RRR --> something at w/o RRR
something <@>QQQ --> something at w/ QQQ
something <@>RRR --> something at w/o RRR
Run Code Online (Sandbox Code Playgroud)
而且我已经预料到第一线了something <@> QQQ --> something at w/ QQQ.
Mar*_*eed 10
它匹配,因为零包含在"任何数字"中.因此,没有空格,后跟空格,匹配"任意数量的空格后面没有Q".
你应该添加另一个先行断言,即你的空格之后的第一件事本身就不是空间.试试这个(未经测试):
<@> *(?!QQQ)(?! )
Run Code Online (Sandbox Code Playgroud)
ETA旁注:只有当只有一个空格时,将量词改为+才会有所帮助; 在一般情况下,正则表达式总是可以占用更少的空间,因此成功.正则表达式想要匹配,并且会以任何可能的方式向后弯曲.所有其他考虑因素(最左边,最长等)都会退居二线 - 如果它可以匹配多种方式,它们会决定选择哪种方式.但匹配总是胜过不匹配.
$string =~ s,<@> *(?!QQQ),at w/o ,;
$string =~ s,<@> *QQQ,at w/ QQQ,;
Run Code Online (Sandbox Code Playgroud)
你的一个问题是你正在分别查看两个正则表达式.首先要求更换字符串QQQ,然后用字符串替换字符串QQQ.从某种意义上说,这实际上是两次检查相同的东西.例如:if (X==0) { ... } elsif (X!=0) { ... }.换句话说,代码可能更好写:
unless ($string =~ s,<@> *QQQ,at w/ QQQ,) {
$string =~ s,<@> *,at w/o,;
}
Run Code Online (Sandbox Code Playgroud)
你总是要小心*量词.由于它匹配零次或多次,它也可以匹配空字符串,这基本上意味着:它可以匹配任何字符串中的任何位置.
负面的外观断言具有相似的质量,在某种意义上它只需要找到一个不同的东西才能匹配.在这种情况下,它将部件匹配"<@> "为<@>+ no space + space,其中space当然是"not" QQQ.你或多或少处于逻辑僵局,因为*量词和负面预测相互对立.
我相信解决这个问题的正确方法是将正则表达式分开,就像我上面所说的那样.允许两个正则表达式执行的可能性是没有意义的.
但是,出于理论目的,需要锚定允许任意数量的空间和负前瞻的工作正则表达式.就像Mark Reed所展示的那样.这可能是最简单的.
<@>(?! *QQQ) # Add the spaces to the look-ahead
Run Code Online (Sandbox Code Playgroud)
不同之处在于,现在空格和Qs彼此锚定,而在它们之前可以单独匹配.要将*量词的重点放在家中,并解决移除额外空格的小问题,您可以使用:
<@> *(?! *QQQ)
Run Code Online (Sandbox Code Playgroud)
这将起作用,因为任何一个量词都可以匹配空字符串.从理论上讲,你可以根据需要添加任意数量的这些,并且它们没有区别(性能除外):/ * * * * * * */在功能上等同于/ */.这里的区别在于可能不存在与Qs结合的空格.