zoukankan      html  css  js  c++  java
  • 【转载】递归正则表达式的一般构造方法

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

    作者: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*

  • 相关阅读:
    CALL FUNCTION 'BAPI_GOODSMVT_CREATE'-(物料凭证创建)
    SAP邮件
    sap人员编制
    ABAP 日期栏函数
    SAP建数据库索引
    去前导零
    SD相关的表
    php 使用 file_exists 还是 is_file
    FastAdmin 的 CRUD 不支持层级模型
    使用 Visual Studio Code (VSCODE)写 C51 (持续更新 2018-04-09)
  • 原文地址:https://www.cnblogs.com/animalize/p/5359276.html
Copyright © 2011-2022 走看看