见这个例子:
str = "aaaaaaaaaaaaaaaaaaaaaa"
Regex.match? ~r/a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaaaaaaaa/, str
#=> true
Regex.match? ~r/a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaaaaaaaa/, str
#=> false
请注意,只有当我向正则表达式添加更多str
时,如果a?
变长,它就不会中断。
答案 0 :(得分:5)
就像@Wiktor指出的那样,这个正则表达式导致一些Regex实现中的指数回溯,包括Erlang使用的一个(PCRE)。 match?
返回普通false
而不是抛出错误的原因是因为Erlang' :re.run/3
如果默认达到此限制则会返回:nomatch
:
iex(1)> str = "aaaaaaaaaaaaaaaaaaaaaa"
"aaaaaaaaaaaaaaaaaaaaaa"
iex(2)> re = ~r/a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaaaaaaaa/
~r/a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?a?aaaaaaaaaaaaaaaaaaaaaa/
iex(3)> Regex.match?(re, str)
false
iex(4)> :re.run(str, re.re_pattern)
:nomatch
:re.run/3
可以通过传递:report_errors
来报告此错误,以确认此Regex确实达到了限制:
iex(5)> :re.run(str, re.re_pattern, [:report_errors])
{:error, :match_limit}
来自文档:
以下是可能的运行时错误:
match_limit
PCRE库设置了限制次数 可以调用内部匹配函数。默认为10,000,000 为Erlang编译的库。如果返回{error,match_limit},则 正则表达式的执行已达到此限制。这是 通常被视为无匹配,这是默认的回报 发生这种情况时的值,但是通过指定report_errors,您就是 由于内部呼叫太多而导致比赛失败时通知。
可以增加限制(这通常是一个坏主意,因为正则表达式将非常慢并且如果用户提供正则表达式则可能导致DoS攻击):
iex(6)> :re.run(str, re.re_pattern, match_limit: 20_000_000)
{:match, [{0, 22}]}
答案 1 :(得分:1)
您的模式不起作用,因为所有模式都匹配在字符串cause catastrophical backtracking issue中的相同位置。
请注意,如果您要匹配0个或更多符号,请使用*
量词:
str = "aaaaaaaaaaaaaaaaaaaaaa"
Regex.match? ~r/a*aaaaaaaaaaaaaaaaaaaaaa/, str
^^
a*
将匹配0个或更多a
个符号。请参阅online Elixir demo。