Go正则表达式嵌套重复报错:匹配50个单词失败
Go正则表达式嵌套重复超限问题解决
问题场景
要匹配最多50个由空格分隔的单词,每个单词为1-32个字符a。使用正则^(a{1,32}\s?){1,50}$编译时触发错误:
error parsing regexp: invalid repeat count: `{1,50}`
但将外层重复次数改为1-31时,正则可正常编译。
原因分析
Go的标准正则引擎是RE2,为避免正则匹配时出现指数级时间复杂度,对嵌套重复的总计数乘积做了限制:当内层重复量词(如{1,32})和外层重复量词(如{1,50})的最大计数乘积超过1000时,会触发编译错误。
原正则中,内层a{1,32}\s?的最大计数为32,外层重复50次,32×50=1600>1000,因此报错;而32×31=992<1000,符合限制,所以能正常编译。
解决方案
方案1:调整正则写法,避免嵌套重复
将嵌套重复结构改为线性串联,规避RE2的计数限制。例如:
// 匹配1-50个单词,单词间用至少一个空格分隔,最后允许带一个可选空格 re, err := regexp.Compile(`^(a{1,32}(?:\s+a{1,32}){0,49})\s?$`)
该写法的逻辑:
- 开头是1个符合要求的单词
- 后面可跟0-49组(空格+符合要求的单词),总单词数控制在1-50
- 末尾允许带一个可选空格,兼容原正则的
\s?逻辑
方案2:分两步验证
如果正则写法调整有局限,可拆分验证逻辑,降低正则复杂度:
- 先用简单正则校验输入仅由
a和空格组成 - 拆分单词后,检查数量是否在1-50之间,且每个单词都是1-32个
a
示例代码:
package main import ( "fmt" "regexp" "strings" ) func main() { baseRe, _ := regexp.Compile(`^[a\s]+$`) wordRe, _ := regexp.Compile(`^a{1,32}$`) testCases := []string{ "a", "a aa aaa", strings.Repeat("a ", 50), strings.Repeat("aaa", 33), strings.Repeat("a ", 51), } for _, tc := range testCases { if !baseRe.MatchString(tc) { fmt.Printf("输入: %q → 不匹配(含非法字符)\n", tc) continue } words := strings.Fields(tc) if len(words) < 1 || len(words) > 50 { fmt.Printf("输入: %q → 不匹配(单词数量不符)\n", tc) continue } valid := true for _, word := range words { if !wordRe.MatchString(word) { valid = false break } } fmt.Printf("输入: %q → 匹配结果:%t\n", tc, valid) } }
内容的提问来源于stack exchange,提问作者user1247196
相关产品推荐
相关产品推荐

