2016-09-15 38 views
2

我有一个和/或正则表达式即(PatternA | PatternB),其中我只在PatternB不存在时才采用PatternA(PatternB总是在PatternA之后出现,但更重要)所以我在PatternA Pipe中放置了一个负向前视。为什么Negative Lookahead超时和/或Pipe

这适用于较短的文本块:

https://regex101.com/r/bU6cU6/5

但在较长的文本块超时:

https://regex101.com/r/bU6cU6/2

我不明白的是,如果我把PatternA与Neg在同一长文本块中独自前行,只需32步即可拒绝它:

https://regex101.com/r/bU6cU6/3

,如果我在同样长的文本块把PatternB单独只需要18个步骤来接受它:

https://regex101.com/r/bU6cU6/4

所以我不知道为什么它正在采取100,000以上/超时首先拒绝(32步),然后用管子接受(18步)。是否有另一种/更好的方法来构建,因此它首先检查PatternA,而不是PatternB,因为现在它正在做一些我不明白从50步到100k +的事情。

+0

在文档中的每个位置执行前瞻。这是非常低效的。您可以在'Option1:'text:'Option1:(?!。* Option2)\ *。*?(?P Bob | David | Ted | Alice)| \ * Option2(?P Juan) –

+0

@WiktorStribiżew这是有道理的。在前面的问题http://stackoverflow.com/questions/39482021/fixing-negative-assertion-for-end-of-string我被告知把它放在字符串的开头,并接受了答案,并继续前进。如果事实上不是正确的方式,也许我应该不接受,因为看起来并不正确。上述和接受的答案在这里都很好地解决了这个问题。 – user3649739

回答

1

与“全局”正则表达式(匹配多个匹配项)一起使用的未锚定周边引起的操作太多,效率低下。它们应该被“锚定”到某个具体的环境中。通常,它们在字符串的开始处(向前)或向后(向后)移动。

对于你的情况,你可以通过在Option1:之后放置它来“锚定”它,以确保它仅在Option1:被匹配后才被执行。

Option1:(?!.*Option2)\*.*?(?P<Capture>Bob|David|Ted|Alice)|\*Option2 (?P<Capture2>Juan) 
     ^^^^^^^^^^^^^ 

this regex demo

一些更多的答案:

我不明白的是,如果我把PatternA与负片向前看独自一人在同样长的文本块只需要32步骤来拒绝它

是的,但你测试它与内部优化ON。禁用它们,你会看到

enter image description here

,如果我在同样长的文本块,只需要18个步骤来接受它把PatternB独自:

像预期的那样找到匹配,在一个非常有效的方式:

enter image description here

+0

好的,我应该在提交之前查看你的答案。我要离开我的,但@user,请接受这个。 –

1

你的主要问题是上厕所的位置kahead。前瞻必须在每个位置进行尝试,并且每次都必须扫描剩余的所有字符。较长的测试字符串长度超过3500个字符;这加起来。

如果你的正则表达式没有锚定,你应该总是试着用一些具体的东西来启动它,这些东西会失败或者很快成功 - 文字是最好的。在这种情况下,显然您可以将后视图移回:Option1:\*(?!.*Option2)而不是(?!.*Option2)Option1:\*。 (注意前面缺少尾部.*;你不需要那个。)

但是当你单独匹配时,为什么PatternA快得多?内部优化。当正则表达式只是(?!.*Option2.*)Option1:\*.*?(?P<Capture>(Bob|David|Ted|Alice))时,正则表达式引擎可以知道匹配必须以Option1:*开头,所以它直接进入该位置进行首次匹配尝试。较长的正则表达式太复杂,并且不会发生优化。

你可以在Regex101上使用“regex debugger”选项来测试,然后检查DISABLE INTERNAL ENGINE OPTIMIZATIONS。步数可以回到超过100,000。

相关问题