使用JavaScript正则校验用户名出现Too much recursion错误如何解决
问题原因
你遇到的是正则表达式的灾难性回溯问题,与$符号、À-ÖØ-öø-ÿ类特殊字符无关。
问题出在正则的嵌套量词结构:([ _]?[A-Za-z0-9À-ÖØ-öø-ÿ]+)+
- 外层分组使用了
+量词,分组内部的字符匹配也使用了+量词,同时分隔符[ _]是可选的?修饰 - 当匹配到不合法字符(比如你示例中的连续空格)时,正则引擎会尝试所有可能的分组拆分方式来匹配规则,长文本下试错的组合数会呈指数级增长,错误位置越靠后耗时越长,最终触发递归超限错误。
修复方案
修改正则结构,消除歧义避免回溯路径,按照你的规则:以字母开头,后续可跟字母、数字,仅允许单个空格/下划线作为分隔符,正则可以改写为:
// 去掉无意义的g修饰符,重构结构消除回溯可能 const reg = /^[A-Za-zÀ-ÖØ-öø-ÿ][A-Za-z0-9À-ÖØ-öø-ÿ]*(?:[ _][A-Za-z0-9À-ÖØ-öø-ÿ]+)*$/ console.log(reg.test("RegExr was created by gskinner_com_and is proudly hosted by Media Temple")); // 输出false,不会出现耗时过长或崩溃问题
重构后的逻辑完全符合你的规则:
- 开头必须是指定范围内的字母
- 可以直接跟0个或多个合法字符(字母、数字、扩展字符)
- 每次出现分隔符
或_后,必须跟至少1个合法字符,从逻辑上避免了连续分隔符的可能,同时没有可选量词的歧义,引擎不需要回溯试错,匹配效率极高。
额外注意事项
- 不要在
test()、exec()这类单次匹配方法中无意义使用g全局修饰符,全局匹配会保留上次匹配的位置索引lastIndex,多次调用同个正则实例会出现意料之外的结果。 - 编写正则时尽量避免「可选元素+嵌套重复量词」的结构,这类结构是灾难性回溯的高发场景。
内容的提问来源于stack exchange,提问作者Caliph Hamid
相关产品推荐
相关产品推荐

