如何解决负前瞻正则表达式贪婪为什么*?过于贪婪
|| 我无法理解否定的超前正则表达式的详细信息。在阅读了正则表达式前瞻,后向和原子组之后,当我发现以下描述时,我认为我对否定前瞻有了一个很好的总结:(?!REGEX_1)REGEX_2
仅在REGEX_1
不匹配时匹配;选中ѭ1之后,将在相同位置开始搜索REGEX_2
。
希望我理解算法,我做了两次句子测试侮辱;我想找到没有特定单词的句子。特别...
侮辱:\'尤玛玛丑陋。而且,她闻起来像一条湿狗。\'
要求:
测试1:返回不带“ ugly”的句子。
测试2:返回不带“ looks”的句子。
测试3:返回不带\'smells \'的句子。
我将测试词分配给$arg
,并使用(?:(?![A-Z].*?$arg.*?\\.))([A-Z].*?\\.)
进行了测试。
(?![A-Z].*?$arg.*?\\.)
是否定前瞻,拒绝带有测试词的句子
([A-Z].*?\\.)
至少匹配一个句子。
关键在于似乎要了解正则表达式引擎在处理否定前瞻后在哪里开始匹配。
预期成绩:
测试1($ arg =“丑陋”):“而且,她闻起来像一条湿狗。”
测试2($ arg = \“ looks \”):\“ Yomama难看。\”
测试3($ arg =“气味”):“ Yomama丑陋。”
实际结果:
测试1($ arg = \“ ugly \”):\“而且,她闻起来像一条湿狗。\”(成功)
测试2($ arg = \“ looks \”):\“ Yomama难看。\”(成功)
测试3($ arg = \“ smells \”):失败,没有匹配项
起初我以为测试3失败了,因为([A-Z].*?\\.)
太贪心了,无法匹配两个句子。但是,ѭ9也不起作用。接下来,我想知道python否定前瞻实现是否存在问题,但是perl给了我完全相同的结果。
最终我找到了解决方案,我不得不使用ѭ11来拒绝表达式中.*?
部分的句点;所以这个正则表达式起作用:(?:(?![A-Z][^\\.]*?$arg[^\\.]*?\\.))([A-Z][^\\.]*?\\.)
题
但是,我还有另一个担心。 \“ Yomama丑陋。\”中没有\“气味\”。因此,如果.*?
应该是非贪婪的匹配,为什么我不能用(?:(?![A-Z].*?$arg.*?\\.))([A-Z].*?\\.)
完成测验3?
编辑
鉴于@bvr推荐使用-Mre=debug
的出色建议,下班后我会再考虑一些。在这一点上,塞思的描述肯定是正确的。到目前为止,我了解到,即使我将非贪婪的.*?
运算符放在NLA中,否定的超前表达式也将尽可能匹配。
Python实现
import re
def test_re(arg,INSULTSTR):
mm = re.search(r\'\'\'
(?: # No grouping
(?![A-Z].*?%s.*?\\.)) # Negative zero-width
# assertion: arg,followed by a period
([A-Z].*?\\.) # Match a capital letter followed by a period
\'\'\' % arg,INSULTSTR,re.VERBOSE)
if mm is not None:
print \"neg-lookahead(%s) MATCHED: \'%s\'\" % (arg,mm.group(1))
else:
print \"Unable to match: neg-lookahead(%s) in \'%s\'\" % (arg,INSULTSTR)
INSULT = \'Yomama is ugly. And,she smells like a wet dog.\'
test_re(\'ugly\',INSULT)
test_re(\'looks\',INSULT)
test_re(\'smells\',INSULT)
Perl实施
#!/usr/bin/perl
sub test_re {
$arg = $_[0];
$INSULTSTR = $_[1];
$INSULTSTR =~ /(?:(?![A-Z].*?$arg.*?\\.))([A-Z].*?\\.)/;
if ($1) {
print \"neg-lookahead($arg) MATCHED: \'$1\'\\n\";
} else {
print \"Unable to match: neg-lookahead($arg) in \'$INSULTSTR\'\\n\";
}
}
$INSULT = \'Yomama is ugly. And,she smells like a wet dog.\';
test_re(\'ugly\',$INSULT);
test_re(\'looks\',$INSULT);
test_re(\'smells\',$INSULT);
输出量
neg-lookahead(ugly) MATCHED: \'And,she smells like a wet dog.\'
neg-lookahead(looks) MATCHED: \'Yomama is ugly.\'
Unable to match: neg-lookahead(smells) in \'Yomama is ugly. And,she smells like a wet dog.\'
解决方法
#!/usr/bin/perl
sub test_re {
$arg = $_[0];
$INSULTSTR = $_[1];
$INSULTSTR =~ /(?:^|\\.\\s*)(?:(?![^.]*?$arg[^.]*\\.))([^.]*\\.)/;
if ($1) {
print \"neg-lookahead($arg) MATCHED: \'$1\'\\n\";
} else {
print \"Unable to match: neg-lookahead($arg) in \'$INSULTSTR\'\\n\";
}
}
$INSULT = \'Yomama is ugly. And,she smells like an wet dog.\';
test_re(\'Yomama\',$INSULT);
test_re(\'ugly\',$INSULT);
test_re(\'looks\',$INSULT);
test_re(\'And\',$INSULT);
test_re(\'And,\',$INSULT);
test_re(\'smells\',$INSULT);
test_re(\'dog\',$INSULT);
结果:
neg-lookahead(Yomama) MATCHED: \'And,she smells like an wet dog.\'
neg-lookahead(ugly) MATCHED: \'And,she smells like an wet dog.\'
neg-lookahead(looks) MATCHED: \'Yomama is ugly.\'
neg-lookahead(And) MATCHED: \'Yomama is ugly.\'
neg-lookahead(And,) MATCHED: \'Yomama is ugly.\'
neg-lookahead(smells) MATCHED: \'Yomama is ugly.\'
neg-lookahead(dog) MATCHED: \'Yomama is ugly.\'
,如果您对Perl使用正则表达式感到好奇,可以使用regex调试器运行:
perl -Dr -e \'\"A two. A one.\" =~ /(?![A-Z][^\\.]*(?:two)[^\\.]*\\.)([A-Z][^\\.]+\\.)/; print \">$1<\\n\"\'
这将产生很多输出供您思考。您将需要使用-DDEBUGGING构建的Perl。
,您的问题是,正则表达式引擎将尽全力匹配(?![A-Z].*?$arg.*?\\.)
,因此对于\“ smells \”,最终将匹配整个字符串。 (然后,中间的句点包含在“ 10”构造中的一个中。)您应该限制否定的超前情况与其他情况所能匹配的尽可能多:
代替:
(?:(?![A-Z].*?$arg.*?\\.))([A-Z].*?\\.)
采用:
(?:(?![A-Z][^.]*$arg[^.]*\\.))([A-Z].*?\\.)
现在,负向超前匹配不能比其他部分匹配更多的字符串,因为它必须在第一时间段停止。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。