[正则表达式]PCRE反向分组引用
在常见的文本匹配场景上,经常会需要用到一些像HTML这样的嵌套标签类型的文本匹配,经过多翻折腾,拼凑出了这样的一条语句
(<([\w]+)>((?1)|[\w\s])*</\2>)
如何理解?
要解析上面的语句是如何运行的,先来了解一下PCRE的反向分组引用机制
(?n)
以括号为单元,紧贴左括号以?号开始,接着引用分组的序号数字,这是反向引用分组的语法
例如,\[([\w]+)-(?1)\]将会匹配像[9-3],[9-9]这样的结构,因为(?1)引用了第一个括号的表达式也就是([\w]+),用来匹配接下来的字符
如何得知分组的序号数字?
例如,\[([\w]+(\s)?)-(.*)\]
分组1将会是([\w]+(\s)?),
而分组2将会是(\s),
想必你已经知道分组3将会是(.*)了。
接下来介绍一个另外的反向分组引用机制
'\n'
以反斜杠开头,接着引用分组的序号数字,这是反向引用分组结果的语法
和(?n)有什么不同?
稍微更改一下刚才的语句就知道了,
现在把\[([\w]+)-(?1)\]更改为\[([\w]+)-\1\],再来匹配一下[9-3],[9-9],没错,现在只能匹配到[9-9]这样的结构了,因为\1引用了第一个括号的表达式也就是([\w]+)匹配的结果用来匹配接下来的字符,而不是直接引用执行
现在回头看看片头给出的语句,已经不难理解了
来解析一番:
假设有以下一条HTML片段
<p> i am <i> genius </i> , do you agree? </p> <p> absulutely not </p>
引擎从第一个分组开始匹配(也就是整一条表达式)
(<)
(然后p,没有更多了,没关系,+不要求更多,继续往下)
(>,一切都很顺利)
(空字符,匹配了[\w\s],继续。。。)
。。。
当来到了下一个标签<i>,转折点在这里,<的出现,让原先一路往右的语句引用了整个式子,此时语句会率先执行向后引用的语句,然后等待匹配结果,当向后引用的语句再次遇到引用怎么办?显然,它的做法也会和它上一层的语句一样,直到匹配没有被继续引用,并且执行到了结尾,所有向后引用的公式会一层层的返回,这个情形类属于函数上的递归算法
改进一下就可以支持tag属性和img这种没有结束tag的标签
(<(div|p|table|tbody|tr|td|a)[\s\w='":;./#!]*>(?:(?1)|[^<]|<(?:img)\s+[^>]+)*<\/\2>)
支持更多的无结束标签tag
(<(?:(div|p|table|tbody|tr|td|a)|(img|meta|link))([\s\w='":;./#!-,]*)>(?(2)((?1)|[^<]|<(?3)(?4)[/]?>)*<\/\2>))
全程用到了哪些语法
#分组捕获
”(?n)“
#反向引用结果
”\n“
#消除分组捕获和反向引用,运用这种语法括号中的表达式将只匹配而不会被捕获,例如(?:[a])([b])\1,\1捕获的分组会是([b])
"(?:)"
#if 流程控制,运用这种语法将会判断先前出现的分组n是否触发了匹配,如果是则启用当前括号分组的规则,例如(a)?(?(1)bb)c,只有当(a)?成功匹配了,接下来才会匹配bb
"(reg)(?(n)trueReg|falseReg)"
备注:
JavaScript并不支持分组捕获(?n),但是支持反向引用结果
[正则表达式]PCRE反向分组引用的更多相关文章
- [正则表达式]PCRE反向分组引用(语法)
正则表达式中,凡出现圆括号(),括号中的匹配内容就会被认为是一个分组: 根据括号从左边出现的顺序命名分组代号,分组代号由1到n(代号0通常被一些语言用来引用整个表达式匹配的结果,即使这个表达式没有分组 ...
- Django url配置 正则表达式详解 分组命名匹配 命名URL 别名 和URL反向解析 命名空间模式
Django基础二之URL路由系统 本节目录 一 URL配置 二 正则表达式详解 三 分组命名匹配 四 命名URL(别名)和URL反向解析 五 命名空间模式 一 URL配置 Django 1.11版本 ...
- PHP 正则表达式(PCRE)
PHP 正则表达式(PCRE) 正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个串是否含有某种子串.将匹配的子串做替换或者从某个串中取出符合某个条件的子串 ...
- Python 正则表达式 利用括号分组
如果想把区号从匹配的电话号码中分离,可以添加括号在正则表达式中创建分组,再使用group()方法,从一个分组中获取匹配的文本 正则表达式字符串中,第一个括号是第一组,第二个括号是第二组.向group( ...
- python正则表达式中的分组 group
维基百科:http://wiki.ubuntu.org.cn/Python%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%93%8D%E4%BD%9C ...
- [正则表达式]PCRE环视功能
设想一下这个问题,假设为了方便长串数字的阅读性,需要为其添加逗号作为分隔,需要怎么做呢? 2569836495 => 2,569,836,495 正则表达式的匹配通常是从左往右的,这导致无法使用 ...
- 廖雪峰Java9正则表达式-2正则表达式进阶-3分组匹配
1.使用括号可以提取字符串 不加括号匹配电话号码 匹配成功后,如何提取想要的字符串? 使用(...)可以分组:"^(\d{3,4})\-(\d{6,8})$" 2.String.m ...
- java中的正则表达式捕获组与引用的概念
今天群里有个人问,怎样用增则表达式匹配三角形的三边,其实只是要匹配三个数字而已,如 301 402 503 开始认为很简单,我就写了一个 "(([1-9]\\d?)\\s){2}$2&q ...
- 正则表达式-python-无捕获分组与分支选择
无捕获分组 当你要将一部分规则作为一个整体对它进行某些操作,比如指定其重复次数时,你需要将这部分规则用 (?:) 把它包围起来. 分支条件 在正则表达式中,分支条件是一个很常用的条件. 满足条件A 或 ...
随机推荐
- [CareerCup] 5.7 Find Missing Integer 查找丢失的数
5.7 An array A contains all the integers from 0 to n, except for one number which is missing. In thi ...
- 基于C/S架构的3D对战网络游戏C++框架_02系统设计(总体设计、概要设计)
本系列博客主要是以对战游戏为背景介绍3D对战网络游戏常用的开发技术以及C++高级编程技巧,有了这些知识,就可以开发出中小型游戏项目或3D工业仿真项目. 笔者将分为以下三个部分向大家介绍(每日更新): ...
- SQLite剖析之临时文件、内存数据库
一.7种临时文件 SQLite中,一个数据库由单个磁盘文件构成,简化了SQLite的使用,因为移动或备份数据库只要拷贝单个文件即可.这也使得SQLite适合用作应用程序文件格式.但是,当在单个文 ...
- servlet的四个作用域
作用域规定的是变量的有效期限,servlet有四个作用域对象,这里只说三个: 一. request作用域: 1.作用范围: 就是指从http请求发起,到服务器处理结束,返回响应的整个过程.在这个过程中 ...
- 风口之下,猪都能飞。当今中国股市牛市,真可谓“错过等七年”。 给你一个回顾历史的机会,已知一支股票连续n天的价格走势,以长度为n的整数数组表示,
转自:http://www.cnblogs.com/ranranblog/p/5845010.html 风口之下,猪都能飞.当今中国股市牛市,真可谓“错过等七年”. 给你一个回顾历史的机会,已知一支股 ...
- Java 中 手动抛出异常: throw new Exception("错误信息") 错误信息的获得
当然需要先用try catch捕获,但注意new Exception("")括号里的字符串其实是异常原因,所以获取是要用ex.getCause().getMessage() int ...
- Redis 学习(二)
Redis可以存储以下5种数据类型 1. String 字符串 整数 浮点 2. List 一个链表 3. Set 无序收集器 4. Hash 无序散列表 5. Zset 有序集合
- delphi 并发取数据库id问题
这段时间有个项目id频繁出现 id冲突的问题 一真找不到原因 后来想到了个办法 在新建取id时先把到到的id保存起来 上代码 望大神指点下 /// <summary> /// 到表中的最大 ...
- Android基础总结(一)
Android项目的目录结构 Activity:应用被打开时显示的界面 src:项目代码 R.java:项目中所有资源文件的资源id Android.jar:Android的jar包,导入此包方可使用 ...
- BZOJ4614 [Wf2016]Oil
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...