• 【转载】递归正则表达式的一般构造方法


    标题:递归正则表达式的一般构造方法

    作者:xhd2015

    原帖:http://tieba.baidu.com/p/4117059926

    =======================

    先说说问题吧,很老套,如何匹配嵌套的<>

    如果你能匹配

    class regex<>

    恭喜你,最初级的会了,往下看


    那么,换成这个

    class regex<class<>>

    如果你只匹配到红色字符,不幸,你错了

    一般表达式对于嵌套的符号对是没有效果的

    并不是所有的正则工具都支持递归,实现递归的关键是能对 “规则”引用。

    没错,对规则引用(而不是对\1之类的捕获组的反向引用)

    如果规则允许嵌套,就意味着允许递归。先看看什么是规则引用,以及和捕获组的反向引用的区别:

    表达式 (\s|\w) 意味着 或者\s,或者\w,加上括号以后,就有一个组编号,假设编号为1,那么,

    规则引用就是 (?1)

    反向引用就是 \1 没有括号

    区别是,规则引用表示将那个表达式完整地应用在这里,因此(\s|\w)(?1)等价于(\s|\w)(\s|\w)

    而捕获组的反向引用就是简单地将匹配到的字符完整地copy到此处

    现在进入正题,规则引用怎么构造递归正则?

    前面说了规则引用是递归的关键,这句话是什么意思呢?

    递归就是自身包含自身,所以,如果规则自身包含自身,那么这就是递归。而很多嵌套的字符串其实也是一种递归。

    对于嵌套<>,一般的规则只能匹配有限深度的<>,下面讨论几种情况

    匹配1深度 <[^<>]*>

    匹配深度2 <[^<>]*<[^<>]*>[^<>]*>

    匹配深度3 ……

    如果亲自动手写一写1-3的深度,你就会发现规则很简单

    我们发现,2是由1递归生成的,因此,我们尝试从2中删除1,用___替代,得到

    <[^<>]*___[^<>]*>

    这里,特殊性可以代表一般性,所以递归式是

    Rn= <[^<>]*Rn-1[^<>]*>

    所以,递归表达式就是

    (<[^<>]*(?1)*[^<>]*>)

    经检验,完全正确。(?1)后面加个*表示同一深度允许有0个或多个<>对。

    一般性方法:(小菜都会)

    1.写出深度1的嵌套表达式

    2.写出深度2的嵌套表达式

    3.用(?n)替换2中1的位置,就是整个递归表达式。(n是所在组的编号)

    这个方法是算法化的,可以由软件实现,即给出符号对,可以生成递归正则

    =======================

    转载者注

    (<[^<>]*(?1)*[^<>]*>)可以这么写:

    <[^<>]*(?0)*[^<>]*>

    其中(?0)表示对整个表达式的递归引用

    再举一例,匹配嵌套类定义,如:
    class regex<
    class innerA<
    class innerC<
    >
    >
    class innerB<
    >
    >
    正则式:\s*class(?:\s+\w+)?<(?:(?0)|\s)*>\s*

  • 相关阅读:
    打包和调试静态库(2)
    打包和调试静态库(1)
    Xcode7--免证书真机调试
    开发者账号申请附录
    AFN3.0封装
    MPMoviePlayerController属性,方法,通知整理
    排序算法03--选择排序
    排序算法02--冒泡排序
    遇到别人留下的storyboard的,你需要一个引导图,但是不知道怎么跳转.
    将UIview描画成虚线等.
  • 原文地址:https://www.cnblogs.com/animalize/p/5359276.html
Copyright © 2020-2023  润新知