平衡组/递归匹配

这里介绍的平衡组语法是由.Net Framework支持的;其它语言/库不一定支持这种功能,或者支持此功能但需要使用不同的语法。

有时我们需要匹配像( 100 * ( 50 + 15 ) )这样的可嵌套的层次性结构,这时简单地使用\(.+\)则只会匹配到最左边的左括号和最右边的右括号之间的内容(这里我们讨论的是贪婪模式,懒惰模式也有下面的问题)。假如原来的字符串里的左括号和右括号出现的次数不相等,比如( 5 / ( 3 + 2 ) ) ),那我们的匹配结果里两者的个数也不会相等。有没有办法在这样的字符串里匹配到最长的,配对的括号之间的内容呢?

为了避免(和\(把你的大脑彻底搞糊涂,我们还是用尖括号代替圆括号吧。现在我们的问题变成了如何把xx <aa <bbb> <bbb> aa> yy这样的字符串里,最长的配对的尖括号内的内容捕获出来?

这里需要用到以下的语法构造:

  • (?'group') 把捕获的内容命名为group,并压入堆栈(Stack)
  • (?'-group') 从堆栈上弹出最后压入堆栈的名为group的捕获内容,如果堆栈本来为空,则本分组的匹配失败
  • (?(group)yes|no) 如果堆栈上存在以名为group的捕获内容的话,继续匹配yes部分的表达式,否则继续匹配no部分
  • (?!) 零宽负向先行断言,由于没有后缀表达式,试图匹配总是失败

如果你不是一个程序员(或者你自称程序员但是不知道堆栈是什么东西),你就这样理解上面的三种语法吧:第一个就 是在黑板上写一个"group",第二个就是从黑板上擦掉一个"group",第三个就是看黑板上写的还有没有"group",如果有就继续匹配yes部 分,否则就匹配no部分。

我们需要做的是每碰到了左括号,就在压入一个"Open",每碰到一个右括号,就弹出一个,到了最后就看看堆栈是否为空--如果不为空那就证明左括号比右括号多,那匹配就应该失败。正则表达式引擎会进行回溯(放弃最前面或最后面的一些字符),尽量使整个表达式得到匹配。

<                         #最外层的左括号
    [^<>]*                #最外层的左括号后面的不是括号的内容
    (
        (
            (?'Open'<)    #碰到了左括号,在黑板上写一个"Open"
            [^<>]*       #匹配左括号后面的不是括号的内容
        )+
        (
            (?'-Open'>)   #碰到了右括号,擦掉一个"Open"
            [^<>]*        #匹配右括号后面不是括号的内容
        )+
    )*
    (?(Open)(?!))         #在遇到最外层的右括号前面,判断黑板上还有没有没擦掉的"Open";如果还有,则匹配失败

>                         #最外层的右括号

平衡组的一个最常见的应用就是匹配HTML,下面这个例子可以匹配嵌套的<div>标签:

<div[^>]*>[^<>]*(((?'Open'<div[^>]*>)[^<>]*)+((?'-Open'</div>)[^<>]*)+)*(?(Open)(?!))</div>

转载于:https://www.cnblogs.com/qiantuwuliang/archive/2011/06/11/2078482.html

.net c# 正则表达式 平衡组/递归匹配相关推荐

  1. .NET正则基础之——平衡组

    1        概述 平衡组是微软在.NET中提出的一个概念,主要是结合几种正则语法规则,提供对配对出现的嵌套结构的匹配..NET是目前对正则支持最完备.功能最强大的语言平台之一,而平衡组正是其强大 ...

  2. 平衡正则 html,正则表达式-利用平衡组匹配html

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? 从下面的HTML代码片段中匹配 到 span#test 标签内容1 2 3 4 5 6 7 8 9 hi~ 虫虫 : 早 ...

  3. js进阶正则表达式10-分组-多行匹配-正则对象的属性(小括号作用:分组,将小括号里面的东西看成一个整体,因为量词只对前一个字符有效)(多行匹配:m)(属性使用:reg.global)...

    js进阶正则表达式10-分组-多行匹配-正则对象的属性(小括号作用:分组,将小括号里面的东西看成一个整体,因为量词只对前一个字符有效)(多行匹配:m)(属性使用:reg.global) 一.总结 1. ...

  4. java 正则 捕获_Java通过正则表达式捕获组中的文本

    1.简介 Java 正则表达式如何捕获组中的文本 ?--请看下文. 2.代码 /** * 版权所有 编程十万个怎么办(www.tah1986.com) */ public class Capturin ...

  5. java中的正则表达式捕获组与引用的概念

    今天群里有个人问,怎样用增则表达式匹配三角形的三边,其实只是要匹配三个数字而已,如 301 402 503 开始认为很简单,我就写了一个   "(([1-9]\\d?)\\s){2}$2&q ...

  6. 正则表达式之 NFA 引擎匹配原理详解

    文章目录 一.为什么要了解引擎匹配原理 二.正则表达式引擎 三.预备知识 (一)字符串组成 (二)占有字符和零宽度 (三)控制权和传动 四.正则表达式简单匹本过程 (一)基础匹配过程 (二)含有匹配优 ...

  7. Python正则表达式: 元字符/转义/分组/匹配原则/re模块属性方法大全

    正则表达式 动机 文本处理已经成为计算机常见工作之一 对文本内容的搜索,定位,提取是逻辑比较复杂的工作 为了快速方便的解决上述问题,产生了正则表达式技术 简介 定义 即文本的高级匹配模式,提供搜索,替 ...

  8. Python正则表达式的几种匹配用法

    Python正则表达式的几种匹配用法 下面列出: 1.测试正则表达式是否匹配字符串的全部或部分regex=ur"" #正则表达式 if re.search(regex, subje ...

  9. Python正则表达式嵌套组

    Python正则表达式嵌套组 组的概念其实就是筛选特定区域的字符串部分,而不是把上下文信息一起给出来,比如,"aaa(.*)bbb"就是筛选出aaa和bbb之间的字符串,而&quo ...

最新文章

  1. linux shell bash 内置变量参考
  2. 皮一皮:自作多情的表率...
  3. SQL 语句快速参考
  4. flutter - 将数字转换为科学记数法并获得指数 flutter
  5. Linux Diff命令用法
  6. 关于linux中的 秘钥认证 ,最清晰解读
  7. 记一次在LAMP中遇到的问题
  8. JavaWeb -- Session实例 -- 自动登录 和 防止表单重复提交(令牌产生器) MD5码
  9. CentOS7下分布式文件系统FastDFS的安装 配置 (单节点)
  10. php配置email支持_使用PHPMailer实现PHP发邮件功能
  11. nodejs文件的读取
  12. 5. Document open() 方法
  13. 标准C语言程序设计第七版pdf,C语言程序设计(向华)7.pdf
  14. QUT期末考试《电子商务概论》思维导图
  15. Y9000P 2022独显直连
  16. Codeforces Round #828 (Div. 3)-赛后总结
  17. instancetype 与 id for Objective-C
  18. 《高质量程序设计指南——C/C++语言》之开篇记
  19. IE主页改不了怎么办
  20. zebra ZT41142 打印机配置网络连接问题

热门文章

  1. 折叠式菜单 html,JQuery实现折叠式菜单的详细代码
  2. char值序列是什么Java_CharSequence和java之间的确切区别
  3. 2021年春季学期-信号与系统-第十五次作业参考答案-第九小题参考答案
  4. Grove Beginner Kits基础实验 Arduino
  5. 基于TPS28225功率MOS半桥电路测试
  6. 拆解多轴步进电机控制器
  7. reactnative 获取定位_react native 获取地理位置的方法示例
  8. pip不是内部 pycharm_PyCharm的简单使用
  9. python mac地址转换_Python MAC地址 获取,过滤,转换 Python MYSQL 数据获取,比较
  10. python pandas for循环_高逼格使用Pandas加速代码,向for循环说拜拜!