浅谈PHP正则中的捕获组与非捕获组


Posted in PHP onJuly 18, 2016

今天遇到一个正则匹配的问题,忽然翻到有捕获组的概念,手册上也是一略而过,百度时无意翻到C#和Java中有对正则捕获组的特殊用法,搜索关键词有PHP时竟然没有相关内容,自己试了一下,发现在PHP中也是可行的,于是总结一下,分享的同时也希望有大神和细心的学习者找到我理解中出现的问题。

什么是捕获组

我们先看一下PHP的正则匹配函数

int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )

前面两项是我们常用的,$pattern是正则匹配模式,$string是要匹配的字符串。

array &$match,它是一个数组,&表示匹配出来的结果会被写入$match中。

int $flags 如果传递了这个标记, 对于每一个出现的匹配返回时会附加字符串偏移量(相对于目标字符串的)。

int $offset 用于指定从目标字符串的某个未知开始搜索(单位是字节)。

我们主要看一下$match的值里会有什么:

$mode = '/a=(\d+)b=(\d+)c=(\d+)/';

$str='**a=4b=98c=56**';

$res=preg_match($mode,$str,$match);

var_dump($match);

结果如下:

array (size=4)
=> string 'a=4b=98c=56' (length=11)
=> string '4' (length=1)
=> string '98' (length=2)
=> string '56' (length=2)

现在我们知道了什么是捕获组,捕获组是正则表达示中以()括起来的部分,每一对()是一个捕获组。

PHP会为它编号,从1开始。至于为什么会从1开始,那是因为PHP把匹配到的完整字符串编号为0。

如果有多个括号或嵌套括号,按左边括号出现的顺序来进行编号,如图:

浅谈PHP正则中的捕获组与非捕获组

按图中的匹配模式匹配时,捕获组的123号分别是红绿蓝。

捕获组的忽略与命名

我们还可以阻止PHP为匹配组的编号:在匹配组中模式前加  ?:

$mode = '/a=(\d+)b=(?:\d+)c=(\d+)/';

这样,匹配结果就会变成:

array (size=3)
=> string 'a=4b=98c=56' (length=11)
=> string '4' (length=1)
=> string '56' (length=2)

当然,我们也可以在括号的内部为它给它独特的名字。

命名子组可以接受(?<name>), (?'name') 以及(?P<name>)语法. 之前版本仅接受(?P<name>)语法.

例如:$mode = '/a=(\d+)b=(?P<sec>\d+)c=(\d+)/';

使用时结果为:

array (size=5)
=> string 'a=4b=98c=56' (length=11)
=> string '4' (length=1)

 'sec' => string '98' (length=2)
=> string '98' (length=2)
=> string '56' (length=2)

在保留索引数组的同时,加上一个关联项,key值为捕获组名。

捕获组的反向引用

我们在用preg_replace()函数进行正则替换时,我们还可以使用 \n 或 $n 来引用第n个捕获组.

$mode = '/a=(\d+)b=(\d+)c=(\d+)/';

$str='**a=4b=98c=56**';

$rp='\1/$2/\3/';

echo preg_replace($mode,$rp,$str);//**4/98/56/**

\1表示捕获组1(4),$2为捕获组2(98),\3为捕获组3(56)。

非捕获组的用法:

为什么称为非捕获组呢?那是因为它们有捕获组的特性,在匹配模式的()中,但是匹配时,PHP不会为它们编组,它们只会影响匹配结果,并不作为结果输出。

/d(?=xxx)    匹配"后面是xxx的一个数字"。

注意格式:只能放在匹配模式字符串之后

例如:

$pattern='/\d(?=abc)/';

$str="ab36abc8eg";

$res=preg_match($pattern,$str,$match);

var_dump($match);//6

匹配的6,因为只有它作为一个数字,后面还有abc。

(?<=xxx) /d 匹配"前面是xxx的一个数字"

注意格式:只能放在匹配模式字符串之前

例如:

$pattern='/(?<=abc)\d/';

$str="ab36abc8eg";

$res=preg_match($pattern,$str,$match);

var_dump($match);//8

匹配的8,因为只有它作为一个数字,后面还有abc。

与(?=xxx)  (?<=xxx)相对的是(?!=xxx)  (?<!=xxx) 它们在=前加了非运算符 “!”

它表示前面/后面不是xxx的字符串,这里就不再举例了。

以上这篇浅谈PHP正则中的捕获组与非捕获组就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

PHP 相关文章推荐
PHP中的string类型使用说明
Jul 27 PHP
解析PHP中常见的mongodb查询操作
Jun 20 PHP
PHP变量内存分配问题记录整理
Nov 27 PHP
PHP使用header()输出图片缓存实例
Dec 09 PHP
PHP JSON格式的中文显示问题解决方法
Apr 09 PHP
win平台安装配置Nginx+php+mysql 环境
Jan 12 PHP
PHP实现导出带样式的Excel
Aug 28 PHP
PHP Mysqli 常用代码集合
Nov 12 PHP
php 静态属性和静态方法区别详解
Apr 09 PHP
删除PHP数组中头部、尾部、任意元素的实现代码
Apr 10 PHP
浅谈PHP中的面向对象OOP中的魔术方法
Jun 12 PHP
golang实现php里的serialize()和unserialize()序列和反序列方法详解
Oct 30 PHP
Yii2.0表关联查询实例分析
Jul 18 #PHP
php 实现301重定向跳转实例代码
Jul 18 #PHP
PHP的openssl加密扩展使用小结(推荐)
Jul 18 #PHP
PHP多进程编程总结(推荐)
Jul 18 #PHP
php 指定范围内多个随机数代码实例
Jul 18 #PHP
php 解决substr()截取中文字符乱码问题
Jul 18 #PHP
Yii2中cookie用法示例分析
Jul 18 #PHP
You might like
php max_execution_time执行时间问题
2011/07/17 PHP
PHP多线程批量采集下载美女图片的实现代码(续)
2013/06/03 PHP
php实现通过ftp上传文件
2015/06/19 PHP
PHP编程之设置apache虚拟目录
2016/07/08 PHP
Yii2创建多界面主题(Theme)的方法
2016/10/08 PHP
php实现产品加入购物车功能(1)
2020/07/23 PHP
ThinkPHP3.2框架自定义配置和加载用法示例
2018/06/14 PHP
PHP中使用CURL发送get/post请求上传图片批处理功能
2018/10/15 PHP
PHP进阶学习之依赖注入与Ioc容器详解
2019/06/19 PHP
一个挺有意思的Javascript小问题说明
2011/09/26 Javascript
javascript中负数算术右移、逻辑右移的奥秘探索
2013/10/17 Javascript
JavaScript中的方法重载实例
2015/03/16 Javascript
JS实现两表格里数据来回转移的方法
2015/05/28 Javascript
js实现文本框输入文字个数限制代码
2015/12/25 Javascript
微信小程序 获取设备信息 API实例详解
2016/10/02 Javascript
老生常谈javascript的类型转换
2016/10/12 Javascript
vue.js中v-on:textInput无法执行事件问题的解决过程
2017/07/12 Javascript
在Vue中使用axios请求拦截的实现方法
2018/10/25 Javascript
使用vue实现多规格选择实例(SKU)
2019/08/23 Javascript
javascript的delete运算符知识点总结
2019/11/19 Javascript
jQuery实现简单聊天室
2020/02/08 jQuery
js实现双人五子棋小游戏
2020/05/28 Javascript
[01:05:40]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS DT第三场
2014/05/24 DOTA
python利用dir函数查看类中所有成员函数示例代码
2017/09/08 Python
Python如何抓取天猫商品详细信息及交易记录
2018/02/23 Python
python 显示数组全部元素的方法
2018/04/19 Python
浅谈python中requests模块导入的问题
2018/05/18 Python
实例分析python3实现并发访问水平切分表
2018/09/29 Python
Django项目使用ckeditor详解(不使用admin)
2019/12/17 Python
Python使用os.listdir和os.walk获取文件路径
2020/05/21 Python
WINDOWS域的具体实现方式是什么
2014/02/20 面试题
酒店员工职业生涯规划
2014/02/25 职场文书
高中生家长寄语大全
2014/04/03 职场文书
社团活动总结书
2014/06/27 职场文书
自查自纠工作情况报告
2014/10/29 职场文书
SQL语句多表联合查询的方法示例
2022/04/18 MySQL