这个简单的正则表达式真的很慢,为什么?

时间:2017-03-31 09:16:03

标签: javascript regex performance hex

我写了这个非常简单的正则表达式,它检查整个字符串是否代表一个或多个十六进制数字(可选地以“0x”开头,用逗号,减号或空白字符分隔):

/^((0x)?[0-9A-F]+[,\-\s]*)+$/i

对我来说,这个正则表达式非常简单,但这个简单的测试完全崩溃了Firefox和Edge,Chrome占用了100%的CPU使用率大约15秒,然后返回预期的结果“false”:

/^((0x)?[0-9A-F]+[,\-\s]*)+$/i.test("012345678901234567890123456789_0");

有谁知道这里有什么问题?

1 个答案:

答案 0 :(得分:3)

当一个组包含两个子模式,其中一个子模式是可选的时,这是catastrophic backtracking(参见your regex demo)的通常情况。

您需要将模式重新组合为

/^(?:0x)?[0-9A-F]+(?:[,\s-]+(?:0x)?[0-9A-F]+)*$/i

现在,它将匹配:

  • ^ - 字符串开头
  • (?:0x)?[0-9A-F]+ - 十六进制数
  • (?:[,\s-]+(?:0x)?[0-9A-F]+)* - 零个或多个序列
    • [,\s-]+ - 1 +空格,,-符号(如果只匹配1,则删除+
    • (?:0x)?[0-9A-F]+ - 十六进制数
  • $ - 字符串结束。

请参阅regex demo