如何强制正则重新匹配,实现列表各元素对应限定符的反向匹配
解决方案
你要实现的是为逗号分隔的所有标识符反向绑定前缀的类型限定符,原有代码输出异常的核心原因是匹配逻辑没有覆盖所有逗号分隔的变量项,且命名捕获值会在回溯时被回滚。你想要的「强制重新匹配」可以通过调整正则结构或者回溯控制动词实现,更推荐用递归结构的实现,逻辑更稳定:
可直接运行的实现代码
"int a, b, c" =~ m{ (?(DEFINE) (?<qualif>\bint\b|\bfloat\b) (?<ident>[_a-zA-Z][_a-zA-Z0-9]*+) ) ^ \s* (?<cur_qualif>(?&qualif)) \s* (?&decl_list) (?(DEFINE) (?<decl_list> # 匹配单个标识符,触发打印 (?<cur_ident>(?&ident)) \s* (?{ print $+{cur_ident} . "\n" . $+{cur_qualif} . "\n" }) # 匹配逗号后递归处理下一个标识符 (?: , \s* (?&decl_list) )? ) ) $ }xxs;
运行后输出完全符合你的预期:
a int b int c int
强制重试的实现方式(不推荐)
如果一定要通过强制重试匹配的方式实现,可以用Perl正则的回溯控制动词(*FAIL)触发匹配失败回溯,同时用local定义全局变量存储捕获值避免回溯回滚:
my $cur_qualif; "int a, b, c" =~ m{ (?(DEFINE) (?<qualifs>\s*(?<qualif>\bint\b|\bfloat\b)\s*+(?{ local $cur_qualif = $+{qualif} })) (?<decl>\s*(?!(?&qualif))(?<ident>[_a-zA-Z][_a-zA-Z0-9]*+)\s*(?{ print $+{ident} . "\n" . $cur_qualif . "\n" })) ) ^ (?&qualifs) (?&decl) (?: , \s* (*FAIL) )? # 匹配到逗号后主动失败触发重试 .* # 兜底匹配避免整体匹配失败 }xxs;
这种方式靠强制回溯实现,性能比递归结构差很多,仅做参考。
内容的提问来源于stack exchange,提问作者AnArrayOfFunctions
相关产品推荐
相关产品推荐

