perl正则表达式——递归模式

记录perl正则表达式之递归模式的个人理解


阅读前需要的基础:

1、perl在模式中引用一个捕获组时,这个组实际捕获的内容将用于反向引用。

	/\b ( \p{alpha}+ ) \s+ \1 \b /x # numbered backref
	/\b ( \p{alpha}+ ) \s+ \g{1} \b /x # alternate syntax
	/\b ( \p{alpha}+ ) \s+ \g{–1} \b /x # relative backref
	/\b (?<word> \p{alpha}+ ) \s+ \k<word> \b /x # named backref


2、扩展的正则表达式,本文中涉及到的部分

扩展

原子性

含义

(? <name>...)

命名捕获分组

(?# ...)

注释,丢弃

(?: ...)

非捕获组

(?{...})

执行嵌入的perl代码

(?&name)

在组name上递归,其引用的是模式,而不是匹配到的内容

匹配引擎递归匹配代码:

?1调用当前所在的组,导致引擎的递归处理,该代码是匹配平衡小括号的代码

/ ( \( (?: [^()]++ | (?1) )*+ \) )/x

[^()]++表示匹配非括号,当检测到有括号时进入分支(?1),调用整个模式自身,继续深入匹配。

想:用当前的模式去匹配第二条分支捕获到的内容,直到没有括号为止。

又想:如果是这样的话,那么次递归调用首先匹配的应该是‘\(’字符(左括号),那么这个模式就只能匹配一种字符串了,那就是"((((string))))",但是实际上能匹配“aa(bb(cc(dd(ee))))”这种更复杂的,所以之前的想法不对。


递归:从内往外算

恩差点被正则匹配的形式忽悠了,递归递归。perl代码如下,做一个深入理解:

my $str = "aaa(s2s(rf(gt(3(eeeee)))))";

print "\nmatching!\n" if($str =~ /^ (?<p0> \w+ ) 
	(?<pattern> (?#这里是第一个捕获组的开始)
	\(  
	(?: (?<p1> [^()]++ ) (?#匹配非括号,并捕获) (?{print "< $` >|< $& >|< $' >\n";})
	|
	(?<p2> (?&pattern) )
	)*+ (?#如果前一个分支失败,递归调用<pattern>命名组)
		(?{ ($+{p0})?(print "p0:$+{p0}"):(print "p0:NULL"); 
			($+{p1})?(print "\tp1:$+{p1}"):(print "\tp1:NULL"); 
			($+{p2})?(print "\t\tp2:$+{p2}\n"):(print "\t\tp2:NULL\n")
		}) (?#打印捕获的命名组 p1 p2)
		(?#匹配非括号,并捕获) (?{print "< $` >|< $& >|< $' >\n";})
	\)
	) (?#第一个捕获组结束)
	$/x);


{print "< $` >|< $& >|< $' >\n";} ## $`表示匹配到的串之前的串,$&表示匹配到的串,$'表示匹配到的串之后的串

分析输出结果如下:

#######这部分可以看到正则是如何一步步递归进入的#############
<  >|< aaa(s2s >|< (rf(gt(3(eeeee))))) >
<  >|< aaa(s2s(rf >|< (gt(3(eeeee))))) >
<  >|< aaa(s2s(rf(gt >|< (3(eeeee))))) >
<  >|< aaa(s2s(rf(gt(3 >|< (eeeee))))) >
<  >|< aaa(s2s(rf(gt(3(eeeee >|< ))))) >
#####命名组p2是每次递归返回的捕获,p1是每次递归进入之前的捕获###############
p0:aaa  p1:eeeee                p2:NULL
<  >|< aaa(s2s(rf(gt(3(eeeee >|< ))))) >
p0:aaa  p1:3            p2:(eeeee)
<  >|< aaa(s2s(rf(gt(3(eeeee) >|< )))) >
p0:aaa  p1:gt           p2:(3(eeeee))
<  >|< aaa(s2s(rf(gt(3(eeeee)) >|< ))) >
p0:aaa  p1:rf           p2:(gt(3(eeeee)))
<  >|< aaa(s2s(rf(gt(3(eeeee))) >|< )) >
p0:aaa  p1:s2s          p2:(rf(gt(3(eeeee))))
<  >|< aaa(s2s(rf(gt(3(eeeee)))) >|< ) >

matching!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值