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

    xiaoxiao2021-12-02  70

    记录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!

    转载请注明原文地址: https://ju.6miu.com/read-679817.html

    最新回复(0)