为何每三位含空格的整数校验正则触发无限递归错误?
解决Ruby正则校验带空格数字串的无限递归问题
问题背景
需要验证任意长度、每三位数字间可加空格的整数字符串,初始使用的Ruby正则出现无限递归报错:
# 报错的正则 /\A (?<d> ( ( (\g<d>[[:space:]])? \d)? \d)? \d) \z/x === "12 123 123"
运行时错误:
SyntaxError: never ending recursion
问题原因
原正则的命名捕获组(?<d>)在可选分支(...)?中直接递归引用自身\g<d>,导致正则引擎陷入无限循环:每次尝试匹配可选分支时,都可以选择递归调用组d,而递归调用又会再次进入同一个可选分支的判断,没有明确终止条件,最终触发无限递归报错。
解决方案
方案1:非递归正则(推荐,性能更优)
采用更直观的非递归结构,直接贴合需求规则:
# 正确的非递归正则 /\A\d{1,3}(?:[[:space:]]\d{3})*\z/x === "12 123 123"
规则说明:
\A:匹配字符串绝对开头\d{1,3}:匹配开头1-3位数字(?:[[:space:]]\d{3})*:非捕获组,匹配0次或多次「空格+3位数字」的组合\z:匹配字符串绝对结尾/x模式:忽略正则内的空白字符,提升可读性
方案2:修正递归正则(仅作演示,不推荐)
如果必须使用递归,需给递归添加明确的终止条件,避免空递归:
# 修正后的递归正则 /\A (?<d> \d{1,3} (?: [[:space:]] \g<d> )? ) \z/x === "12 123 123"
规则说明:
- 命名组
d先匹配基础的1-3位数字(终止条件) - 再可选匹配「空格+递归调用组
d」,确保递归必须依赖前面的空格和数字,不会触发无限空循环
测试验证
- 有效匹配:
"12"、"123"、"12 123"、"12 123 123" - 无效匹配:
" 123"(开头含空格)、"123 "(结尾含空格)、"12 12"(末尾组不足3位)、"12a123"(含非数字字符)
内容的提问来源于stack exchange,提问作者Nakilon
相关产品推荐
相关产品推荐

