Perl正则匹配非递归花括号块时如何拦截所有全空白行?
Perl 非递归花括号块匹配正则修正方案
原有正则缺陷
原有规则仅在外层普通内容匹配时增加了全空白行拦截,内层花括号匹配直接使用[{][^{}]*[}]规则,未对内部内容做全空白行校验,导致内层花括号中隐藏的全空白行会被漏判,违反无全空白行约束。
修正后完整代码
#!/usr/bin/env perl use strict; use warnings; use Data::Dumper qw(Dumper); $Data::Dumper::Sortkeys = 1; use feature 'say'; my $sgx=join('', # 编译为正则的字符串 '(?m)^', # 锚定行首,而非字符串起始位置 '(?<curl>[{]', # 最外层花括号起始 '(?<insd>', # 花括号内部内容段起始 '(?<jjjj>\w)', # 匹配起始标识字符 '(', # 起始字符后允许的内容规则开始 '(?!\n\s*\n)', # 负向前瞻:后续不允许出现全空白行 '[^{}]', # 匹配非花括号字符 '|', # 逻辑或 '(', # 内层花括号块起始 '[{]', # 内层花括号起始符 # 内层内容增加全空白行拦截,仅允许非花括号字符,杜绝深层嵌套 '(?:(?!\n\s*\n)[^{}])*', '[}]', # 内层花括号结束符 ')', # 内层花括号块结束 ')', # 允许内容规则结束 '*', # 上述内容可出现任意次 ')', # 内部内容段结束 '[}])', # 最外层花括号结束 ); say qr/$sgx/; $/=undef; my $data=<DATA>; my@data=grep{/\S/} split /#/,$data; for(@data) { say '===================================================================================='; print $_; say '------------------------------------------'; if($_=~/$sgx/) { print Dumper\%+; } else { say 'no match'; } } __DATA__ # {A{hey{nested{nested, also all-white line, two reasons SHOULD NOT MATCH}}}}pig # {A{hey{nested{nested, SHOULD NOT MATCH}}}}pig # whoopee {compliant, should match \footnotesize{funny}\normalsize{}\small{}} dogs\textbf{outside} # {MUST NOT MATCH because all-white line tag{A}big{}} # {MUST NOT MATCH because all-white line tag{A }big{}}
核心修改逻辑
- 严格遵守非递归约束:内层花括号内仅允许匹配非花括号字符,从规则层面禁止三层及以上嵌套,避免正则引擎无边界回溯耗尽内存
- 补全内层全空白行拦截:给内层花括号的内容匹配增加和外层一致的负向前瞻校验,每匹配一个字符前先判断后续是否存在
\n\s*\n格式的全空白行,彻底覆盖内层隐藏全空白行的漏判场景 - 兼容原有匹配逻辑:保留原有的行首锚定、命名捕获组规则,原有合规匹配场景不受影响
测试验证结果:前2组存在多层递归嵌套的样本、第4组外层含全空白行的样本、第5组内层含全空白行的样本均返回
no match,第3组合规样本正常匹配捕获内容,完全满足约束要求。
内容的提问来源于stack exchange,提问作者Jacob Wegelin
相关产品推荐
相关产品推荐

