Regex Perl中带*修饰符的负先行断言
我有一个(我认为是)消极的前瞻断言Regex Perl中带*修饰符的负先行断言,regex,perl,negative-lookahead,regex-lookarounds,Regex,Perl,Negative Lookahead,Regex Lookarounds,我有一个(我认为是)消极的前瞻断言*(?!QQQ),如果测试的字符串是一个,后跟任意数量的空格(包括零),然后不后跟QQQ,我希望匹配这个断言 但是,如果测试的字符串是QQQ,则正则表达式匹配 我不明白为什么会出现这种情况,如果能在这件事上得到任何帮助,我将不胜感激 这是一个测试脚本 use warnings; use strict; my @strings = ('something <@> QQQ', 'something <@> RR
*(?!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;
}
使用警告;
严格使用;
我的@strings=('something QQQ',
“某物RRR”,
“什么QQQ”,
"注册登记";;
为映射{$\.-->.rep($\)}(@strings)打印“$\\ n”;
副代表{
我的$string=shift;
$string=~s,*(?!QQQ),在w/o处,;
$string=~s,*QQQ,位于w/QQQ,;
返回$string;
}
这张照片
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
something QQQ-->不带QQQ的某物
某物RRR-->无RRR的某物
某物QQQ-->某物在w/QQQ
某物RRR-->无RRR的某物
我希望第一行是
something QQQ-->在w/QQQ
匹配的东西,因为“任意数”中包含零。所以没有空格,后面跟一个空格,匹配“任何数量的不跟Q的空格”
您应该添加另一个前瞻性断言,即空格后面的第一个东西本身不是空格。试试这个(未经测试):
*(?!QQQ)(?!)
ETA旁注:只有当正好有一个空格时,将量词改为+才有帮助;在一般情况下,正则表达式总是可以少占一个空间,从而获得成功。正则表达式想要匹配,并且会尽可能地向后弯曲以实现匹配。所有其他考虑因素(最左边的、最长的等)都放在次要位置——如果它可以匹配多条路径,则它们决定选择哪条路径。但匹配总是胜过不匹配
$string =~ s,<@> *(?!QQQ),at w/o ,;
$string =~ s,<@> *QQQ,at w/ QQQ,;
您必须始终小心使用*
量词。因为它匹配零次或多次,所以它也可以匹配空字符串,这基本上意味着:它可以匹配任何字符串中的任何位置
否定环顾断言也有类似的性质,即它只需要找到一个不同的东西来匹配。在这种情况下,它将部分“
匹配为
+无空格+空格,其中空格当然是“not”QQQ
。在这里,您或多或少处于一种逻辑僵局,因为*
量词和否定的前瞻性相互抵消
我相信解决这个问题的正确方法是分离正则表达式,就像我在上面展示的那样。允许两个正则表达式都被执行是没有意义的
然而,出于理论目的,需要锚定一个工作正则表达式,该正则表达式既允许任意数量的空格,也允许负前瞻。就像我们所展示的那样。这个可能是最简单的
<@>(?! *QQQ) # Add the spaces to the look-ahead
这将起作用,因为任何一个量词都可以匹配空字符串。从理论上讲,您可以根据需要添加任意数量的代码,这不会产生任何影响(性能除外):
/***/
在功能上等同于/*/
。这里的区别是,与Qs组合的空格可能不存在。正则表达式引擎将回溯,直到找到匹配项,或者直到无法找到匹配项为止。在本例中,它发现以下匹配项:
+--------------- Matches "<@>".
| +----------- Matches "" (empty string).
| | +--- Doesn't match " QQQ".
| | |
--- ---- ---
'something <@> QQQ' =~ /<@> [ ]* (?!QQQ)/x
+--------------匹配“”。
|+-------------匹配“”(空字符串)。
||+---与“QQQ”不匹配。
| | |
--- ---- ---
'something QQQ'=~/[]*(?!QQQ)/x
你所需要做的就是把事情弄得乱七八糟。替换
/<@>[ ]*(?!QQQ)/
/[]*(?!QQQ)/
与
/(?![]*QQQ)/
或者可以使正则表达式只匹配所有空格:
/<@>[ ]*+(?!QQQ)/
/<@>[ ]*(?![ ]|QQQ)/
/<@>[ ]*(?![ ])(?!QQQ)/
/[]*+(?!QQQ)/
/[]*(?![]| QQQ)/
/[]*(?![])(?!QQQ)/
PS-空格很难看到,所以我使用
[]
使它们更可见。无论如何,它都会得到优化。(?=\S)
应该是(?=[^])
(如果下一个字符是制表符)。实际上,它应该是(?!)
(以防它是字符串的结尾)。添加+
可以修复匹配,但我不知道为什么。等等,我想我找到了[]*+
确保即使打破了匹配,也能抓取所有可用的空格,而[]*
将在不打破匹配的情况下抓取尽可能多的空格。@flies,因为=“=~/*+/
只能匹配”
。它不会回溯到匹配的“
”,因此它无法再找到匹配的/*/
。/*+/
应该表示“查找零个或多个空格,一次或多次”,这到底是如何工作的?关于+
贪婪并占用多余空间的内容?@TLP,不,当+
应用于量词(例如*
)时,它会阻止通过该量词进行回溯。(有点像?
如何修改*
的贪婪)/*+/
与/(?>*)/
是一样的。
+--------------- Matches "<@>".
| +----------- Matches "" (empty string).
| | +--- Doesn't match " QQQ".
| | |
--- ---- ---
'something <@> QQQ' =~ /<@> [ ]* (?!QQQ)/x
/<@>[ ]*(?!QQQ)/
/<@>(?![ ]*QQQ)/
/<@>[ ]*+(?!QQQ)/
/<@>[ ]*(?![ ]|QQQ)/
/<@>[ ]*(?![ ])(?!QQQ)/