这看起来像一个简单的正则表达式,没有反引用,没有“any”字符,我甚至敢说它可以被Thomson DFA解析。它甚至可以工作,但是被非常简单的非匹配项阻塞了。你知道吗
{\s*?
ngx_string\("(?P<name>[a-z0-9_]+)"\)\s*?,\s*?
(?P<where>(([A-Z0-9_]+)\s*\|?)+?)\s*?,\s*?
(?P<bla>[^\n}]+?)\s*?,\s*?
(?P<bla2>[^\n}]+?)\s*?,\s*?
(?P<bla3>[^\n}]+?)\s*?,\s*?
(?P<bla4>[^\n}]+?)\s*?
}
+ re.MULTILINE | re.VERBOSE
我目前正在Python2.7.8上尝试这一点(但是链接的gist在py3.4上也失败了;另外linux、x86-64、Ubuntu、PCRE在[least/proc//maps中静态链接也没有显示任何有趣的内容)。你知道吗
这很好地解释了:
{ ngx_string("daemon"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
0,
offsetof(ngx_core_conf_t, daemon),
NULL },
这就是乐趣的终点:
{ ngx_string("off"), NGX_HTTP_REQUEST_BODY_FILE_OFF },
{ ngx_string("on"), NGX_HTTP_REQUEST_BODY_FILE_ON },
此外,更多数据:
把第二行改成这个
(?P<where>(([A-Z0-9_]{1,20})\s*\|?){1,6}?)\s{0,10}?,\s{0,10}?
,它最终在合理的时间内完成,但指数爆炸仍然存在,只是可以承受:
trying { ngx_string("off"), NGX_HTTP_REQUEST_BODY_FILE
Took 0.033483 s
trying { ngx_string("off"), NGX_HTTP_REQUEST_BODY_FILE_
Took 0.038528 s
trying { ngx_string("off"), NGX_HTTP_REQUEST_BODY_FILE_O
Took 0.044108 s
trying { ngx_string("off"), NGX_HTTP_REQUEST_BODY_FILE_OF
Took 0.053547 s
另外,有趣的是,一个基于JS的Python regex(仿真器?)解析器可以把它当作PCRE冠军的早餐来吃:https://www.debuggex.com/r/S__vSvp8-LGLuCLQ
哦,也许有人应该创建一个病理正则表达式标签:|
这就是你的正则表达式爆炸。读http://www.regular-expressions.info/catastrophic.html。你知道吗
每次失败时,它都会返回一步以检查是否存在错误匹配。这个正在为regex引擎创建大量的步骤和可能性。你知道吗
问题是原始正则表达式中的
(([A-Z0-9_]+)\s*\|?)+?
或测试正则表达式中的(([A-Z0-9_]{1,20})\s*\|?){1,6}?
。{1,20}
和{1,6}
只起到抑制指数回溯的作用。你知道吗由于
\s*
和\|?
是可选的,当输入只包含[A-Z0-9_]
而不包含空格或条|
,但与regex的其余部分不匹配时,regex可以扩展到指数回溯(([A-Z0-9_]+))+?
的经典示例。你知道吗例如,匹配
(?P<where>(([A-Z0-9_]+)\s*\|?)+?)\s*?,\s*?
和AAAAAAAAAAAAAA
(,
丢失)将导致引擎检查所有拆分字符串的可能性,每个标记在外部重复的不同迭代中匹配:仔细看,regex的其余部分也有过多的回溯问题。你知道吗
以
(?P<bla2>[^\n}]+?)\s*?,\s*?
为例。[^\n}]
可以匹配空格(或制表符,或许多其他空格字符),因此\s
也可以匹配。如果不匹配的输入包含一长串空格,这可能会导致过度回溯。也可能存在正确性问题,因为,
也可以与[^\n}]
匹配。你知道吗另一方面,Python
re
是一个NFA引擎,没有任何优化来缓解指数回溯问题。你知道吗要减轻指数回溯:
[^\n}]
的过度回溯和正确性问题仍然没有得到解决。如果参数不在不同的行上,函数调用中的,
可能会被错误地识别为外部块{}
的一部分。你知道吗一般的解决方案需要递归正则表达式,因为您可以调用函数作为参数传递其结果,例如
offsetof(ngx_core_conf_t, daemon)
,但是递归正则表达式特性在re
包中不可用。一个不太通用的解决方案是匹配到某些级别的嵌套括号,例如1级嵌套:整个正则表达式是:
DEMO
有两个注意事项:
<bla*>
捕获组的末尾将包含空格。如果您想删除空格,和防止可能的过度回溯,regex会更长一些。您可以尝试将\s*
之前的,
添加回this demo here。你知道吗()
不是任何字符串文本的一部分。你知道吗相关问题 更多 >
编程相关推荐