我写了这个非常简单的正则表达式,它检查整个字符串是否代表一个或多个十六进制数字(可选地以“0x”开头,用逗号,减号或空白字符分隔):
/^((0x)?[0-9A-F]+[,\-\s]*)+$/i
对我来说,这个正则表达式非常简单,但这个简单的测试完全崩溃了Firefox和Edge,Chrome占用了100%的CPU使用率大约15秒,然后返回预期的结果“false”:
/^((0x)?[0-9A-F]+[,\-\s]*)+$/i.test("012345678901234567890123456789_0");
有谁知道这里有什么问题?
答案 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。