PHP正则表达式之捕获组与非捕获组


Posted in PHP onNovember 06, 2015

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

什么是捕获组

捕获组语法:

字符  描述 示例
(pattern) 匹配pattern并捕获结果,自动设置组号。  (abc)+d 匹配abcd或者abcabcd
(?pattern) 或 (?'name'pattern) 匹配pattern并捕获结果,设置name为组名。  
\num 对捕获组的反向引用。其中 num 是一个正整数。 (\w)(\w)\2\1 匹配abba
\k 或 \k' name ' 对命名捕获组的反向引用。其中 name 是捕获组名。 (?\w)abc\k 匹配xabcx

我们先看一下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)
  0 => string 'a=4b=98c=56' (length=11)
  1 => string '4' (length=1)
  2 => string '98' (length=2)
  3 => string '56' (length=2)

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

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

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

PHP正则表达式之捕获组与非捕获组

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

捕获组的忽略与命名

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

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

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

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

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

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

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

使用时结果为:

array (size=5)
 0 => string 'a=4b=98c=56' (length=11)
 1 => string '4' (length=1)
 'sec' => string '98' (length=2)
 2 => string '98' (length=2)
 3 => 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)。

非捕获组的用法:

非捕获组语法:

字符  描述 示例
(?:pattern) 匹配pattern,但不捕获匹配结果。 'industr(?:y|ies) 匹配'industry'或'industries'。
(?=pattern) 零宽度正向预查,不捕获匹配结果。 'Windows (?=95|98|NT|2000)' 匹配 "Windows2000" 中的 "Windows" 不匹配 "Windows3.1" 中的 "Windows"。
(?!pattern) 零宽度负向预查,不捕获匹配结果。 'Windows (?!95|98|NT|2000)' 匹配 "Windows3.1" 中的 "Windows" 不匹配 "Windows2000" 中的 "Windows"。
(? 零宽度正向回查,不捕获匹配结果。 '2000 (?
(? 零宽度负向回查,不捕获匹配结果。 '2000 (?

为什么称为非捕获组呢?那是因为它们有捕获组的特性,在匹配模式的()中,但是匹配时,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的中问验证码
Nov 25 PHP
PHP CURL模拟登录新浪微博抓取页面内容 基于EaglePHP框架开发
Jan 16 PHP
PHP实现AES256加密算法实例
Sep 22 PHP
php实现图片上传时添加文字和图片水印技巧
Apr 18 PHP
Yii2框架BootStrap样式的深入理解
Nov 07 PHP
php获取今日开始时间和结束时间的方法
Feb 27 PHP
php base64 编码与解码实例代码
Mar 21 PHP
TP3.2批量上传文件或图片 同名冲突问题的解决方法
Aug 01 PHP
php实现与python进行socket通信的方法示例
Aug 30 PHP
PHP实现的策略模式简单示例
Aug 25 PHP
php生成毫秒时间戳的实例讲解
Sep 22 PHP
Laravel框架查询构造器简单示例
May 08 PHP
php创建无限级树型菜单
Nov 05 #PHP
详解PHP中instanceof关键字及instanceof关键字有什么作用
Nov 05 #PHP
PHP递归创建多级目录
Nov 05 #PHP
PHP中的静态变量及static静态变量使用详解
Nov 05 #PHP
PHP环境中Memcache的安装和使用
Nov 05 #PHP
php生成gif动画的方法
Nov 05 #PHP
浅析PHP中call user func()函数及如何使用call user func调用自定义函数
Nov 05 #PHP
You might like
PHP中的array数组类型分析说明
2010/07/27 PHP
php操作JSON格式数据的实现代码
2011/12/24 PHP
使用PHP强制下载PDF文件示例
2014/01/17 PHP
Zend Framework基于Command命令行建立ZF项目的方法
2017/02/18 PHP
[原创]PHP实现字节数Byte转换为KB、MB、GB、TB的方法
2017/08/31 PHP
DOM下的节点属性和操作小结
2009/05/14 Javascript
网页中CDATA标记的说明
2010/09/12 Javascript
CSS和JS标签style属性对照表(方便js开发的朋友)
2010/11/11 Javascript
JS运行耗时操作的延时显示方法
2010/11/19 Javascript
对setInterval在火狐和chrome切换标签产生奇怪的效果之探索,与解决方案!
2011/10/29 Javascript
解决jquery submit()提交表单提示:f[s] is not a function
2013/01/23 Javascript
JS页面延迟执行一些方法(整理)
2013/11/11 Javascript
调用DOM对象的focus使文本框获得焦点
2014/02/19 Javascript
javascript框架设计之浏览器的嗅探和特征侦测
2015/06/23 Javascript
WordPress 单页面上一页下一页的实现方法【附代码】
2016/03/10 Javascript
js判断空对象的实例(超简单)
2016/07/26 Javascript
JavaScript面试题大全(推荐)
2016/09/22 Javascript
promise处理多个相互依赖的异步请求(实例讲解)
2017/08/03 Javascript
vue项目中全局引入1个.scss文件的问题解决
2019/08/01 Javascript
nodejs制作小爬虫功能示例
2020/02/24 NodeJs
Antd中单个DatePicker限定时间输入范围操作
2020/10/29 Javascript
python中执行shell命令的几个方法小结
2014/09/18 Python
Python求解平方根的方法
2015/03/11 Python
理解Python中函数的参数
2015/04/27 Python
Python实现完整的事务操作示例
2017/06/20 Python
在CMD命令行中运行python脚本的方法
2018/05/12 Python
Python GUI Tkinter简单实现个性签名设计
2018/06/19 Python
flask框架自定义过滤器示例【markdown文件读取和展示功能】
2019/11/08 Python
python图形开发GUI库pyqt5的基本使用方法详解
2020/02/14 Python
戴尔美国官方折扣店:Dell Outlet
2018/02/13 全球购物
美国时尚大码女装购物网站:Avenue
2019/05/24 全球购物
英国领先的露营和露营车品牌之一:OLPRO
2019/08/06 全球购物
体育系毕业生求职自荐信
2014/04/16 职场文书
教师民族团结演讲稿
2014/08/27 职场文书
建立共青团委员会的请示
2019/04/02 职场文书
CSS实现九宫格布局(自适应)的示例代码
2022/02/12 HTML / CSS