java问题中的regexp
我在测试NLP系统时发现了一些问题。我有一个java正则表达式java问题中的regexp,java,regex,Java,Regex,我在测试NLP系统时发现了一些问题。我有一个java正则表达式“(.\\\\\s*)*Dendryt.*”,对于string“v目录表”…..,它只是不停止计算 很明显,这个正则表达式的复杂性非常高,我将尝试重构它。你对我未来的正则表达式开发有什么建议吗 谢谢。通过重复包含重复量词的组,您将遇到。随后的组合爆炸(给定足够的输入)将导致(tada!)堆栈溢出 简化,您的正则表达式尝试 (.*.\s*)匹配任何连续字符,包括点和空格,后跟一个点,后跟零个或多个空格,然后 (…)*重复此操作任意次数
“(.\\\\\s*)*Dendryt.*”
,对于string“v目录表”…..
,它只是不停止计算
很明显,这个正则表达式的复杂性非常高,我将尝试重构它。你对我未来的正则表达式开发有什么建议吗
谢谢。通过重复包含重复量词的组,您将遇到。随后的组合爆炸(给定足够的输入)将导致(tada!)堆栈溢出
简化,您的正则表达式尝试
(.*.\s*)
匹配任何连续字符,包括点和空格,后跟一个点,后跟零个或多个空格,然后
(…)*
重复此操作任意次数
Dendryt
只有当它尝试匹配“Dendryt”时
由于此操作失败,引擎将返回,尝试不同的排列。可能性几乎是无穷无尽的
为了说明这一点,下面是RegexBuddy的regex调试器在简化版数据上的屏幕截图:
100万次置换后,引擎停止运行
您的正则表达式会更好(在将其转换为Java字符串时,不要忘记避开反斜杠):
在这种情况下,*+
,一个所谓的所有格量词,一旦匹配就会拒绝回溯。这样,正则表达式引擎可能会更快地失败,但仍然很糟糕,因为(.*)
匹配任何东西,甚至点
([^.]*)(\.\s*)*+Dendryt
是安全的,除非您的数据可以在“虚线位”之前包含点。总而言之,请更清楚地说明您的要求,然后可以构建更好的正则表达式。尝试以下方法:
"[^.]*+(?>\\.\\s*)*+Dendryt.*"
[^.]*+
消耗第一个点之前的所有内容,而+
生成*
,因此正则表达式永远不会回溯到该点
(?>\\.\\s*)
是一个:它匹配一个点和任何后续空格,就像它是一个单位一样。如果正则表达式引擎必须回溯到该点,它将直接跳过该点,转到组开始匹配的位置
但它不会回到这一点,因为我把这个组的量词也设为所有格。我想说明原子群的用法,但我可以将\\s*
设为所有格,或者两者兼而有之
所有格量词和原子组完全禁用回溯,但并不总是可以使用它们。当您必须允许回溯时,将其保持在最小值;不要让量词消耗过多。特别是,正如Tim所说,避免嵌套的量词和可以匹配相同事物的量化子表达式
事实上,避免使用
*
和+
是一个很好的练习;它迫使你思考它的机制。如果没有您想要匹配的特定内容,请考虑您不想要匹配的内容,例如我使用[^.]*
代替正则表达式中的第一个*
。正则表达式的这部分(?:....*.\s*)*
表示获取尽可能多的具有
文字点,如果是连续线,则在末尾。这是必需的,直到最后找到
Dendryt
literal。一旦找到它,还可以得到该行的剩余部分
使用一个简单的原子群(?>\uux)
就可以很容易地做到这一点 但是,由于它是原子的,如果在组中使用
*
,它将不会停止检查是否找到最终的
Dendryt
,因为它不会返回
解决方案是使用惰性量词*?
。然后原子组将允许检查最后一个
Dendryt
注意,我不确定您的真正意图是什么,只是使用正则表达式
提供以说明其目前的工作方式,并提供不适用的等效项
导致回溯问题(我看到的是)
解决方案:
(?>.*.\.\s*)*Dendryt.*
非常感谢,非常有帮助!:)
"[^.]*+(?>\\.\\s*)*+Dendryt.*"