灾难性回溯搜索括号中的数字
Posted
技术标签:
【中文标题】灾难性回溯搜索括号中的数字【英文标题】:Catastrophic backtracking searching for numbers in brackets 【发布时间】:2021-06-18 08:05:41 【问题描述】:使用这个正则表达式:\((\W*\d*\W*)*\)
我正在寻找括号内的数字。这些数字可以被任何符号包围,但不能被字符包围,并且这种模式可以在括号内出现很多次,我的意思是我需要在这里匹配所有内容:
但不是:
(8j) (a888) (1, 2; 12.13; 25.26; 35.36; 43.45; 52.56; 59,6o)最后一个例子给了我一个灾难性的回溯错误。我怎样才能避免这个错误?我真的不明白该怎么做......
【问题讨论】:
如果您总是期望至少一位数字,那么您不应该在\d
之后以及捕获组之后使用*
量词。请改用+
。
你可以用下面的(?:\(|\G(?!^))[^a-z\n\)]*?\K\d+(?:\.\d+)?(?=[^a-z\n\)]*\))
@silkfire (\W*\d+\W*)+
仍然有灾难性的回溯,因为两个相邻的\W*
在一个组重复中(通过使用(\W*\d+)+\W*
来解决这个问题),并且\W*
可能不匹配任何相邻的东西数字可能是外部组的重复(通过使用(\W*\d)+\W*
或\W*\d+(\W+\d+)*\W*
修复)。
【参考方案1】:
您可以将您的正则表达式更改为 \([\W\d]*\)
,这将匹配和不匹配您的示例。
见https://regex101.com/r/DNmuEb/1/
【讨论】:
我认为这是最好和更清洁的解决方案。谢谢。【参考方案2】:\((\W*\d*\W*)*\)
的灾难性回溯是由于嵌套的可选量词造成的,一切都是可选的。
注意\W
也可以匹配(
和)
您可以匹配除字符 A-Z a-z 或括号之外的任何空白字符,如果您需要匹配所有内容,则在括号之间至少声明一个数字
\((?=[^()\d]*\d)[^A-Za-z()]+\)
\(
匹配(
(?=[^()\d]*\d)
在括号之间至少声明一个数字
[^A-Za-z()]+
匹配除字符 A-Z a-z ( ) 以外的任何字符的 1+ 倍,如果您想扩展它,可以添加更多
\)
匹配)
Regex demo
【讨论】:
以上是关于灾难性回溯搜索括号中的数字的主要内容,如果未能解决你的问题,请参考以下文章