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中文件上传的安全问题
Oct 09 PHP
PHP树的代码,可以嵌套任意层
Oct 09 PHP
Windows下的PHP5.0详解
Nov 18 PHP
php 在线打包_支持子目录
Jun 28 PHP
php的memcached客户端memcached
Jun 14 PHP
php简单开启gzip压缩方法(zlib.output_compression)
Apr 13 PHP
PHP 过滤页面中的BOM(实现代码)
Jun 29 PHP
PHP 线程安全与非线程安全版本的区别深入解析
Aug 06 PHP
PHP基于PDO调用sqlserver存储过程通用方法【基于Yii框架】
Oct 07 PHP
PHP 实现人民币小写转换成大写的方法及大小写转换函数
Nov 17 PHP
详解Yaf框架PHPUnit集成测试方法
Dec 27 PHP
PHP7基于curl实现的上传图片功能
May 11 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的面试题集
2006/11/19 PHP
关于php mvc开发模式的感想
2011/06/28 PHP
php判断用户是否关注微信公众号
2016/07/22 PHP
Prototype使用指南之array.js
2007/01/10 Javascript
javascript数组使用调用方法汇总
2007/12/08 Javascript
Three.js源码阅读笔记(物体是如何组织的)
2012/12/27 Javascript
基于jQuery实现仿淘宝套餐选择插件
2015/03/04 Javascript
PhantomJS快速入门教程(服务器端的 JavaScript API 的 WebKit)
2015/08/06 Javascript
JavaScript学习笔记整理之引用类型
2016/01/22 Javascript
JS组件Bootstrap Select2使用方法详解
2020/04/17 Javascript
Bootstrap 布局组件(全)
2016/07/18 Javascript
jquery 实时监听输入框值变化的完美方法(必看)
2017/01/26 Javascript
js实现瀑布流效果(自动生成新的内容)
2017/03/16 Javascript
JavaScript实现微信号随机切换代码
2018/03/09 Javascript
jQuery AJAX 方法success()后台传来的4种数据详解
2018/08/08 jQuery
php结合js实现多条件组合查询
2019/05/28 Javascript
vue中使用element组件时事件想要传递其他参数的问题
2019/09/18 Javascript
jQuery操作元素追加内容示例
2020/01/10 jQuery
[03:22]DOTA2超级联赛专访单车:找到属于自己的英雄
2013/06/08 DOTA
python 切片和range()用法说明
2013/03/24 Python
Python实现的圆形绘制(画圆)示例
2018/01/31 Python
Python编程图形库之Pillow使用方法讲解
2018/12/28 Python
TensorFlow卷积神经网络之使用训练好的模型识别猫狗图片
2019/03/14 Python
python实现银联支付和支付宝支付接入
2019/05/07 Python
Python3 requests文件下载 期间显示文件信息和下载进度代码实例
2019/08/16 Python
python thrift 实现 单端口多服务的过程
2020/06/08 Python
Python+Xlwings 删除Excel的行和列
2020/12/19 Python
详解CSS3+JS完美实现放大镜模式
2020/12/03 HTML / CSS
黑猩猩商店:The Chimp Store
2020/02/12 全球购物
JSP和EJB可以共享HttpSession么?EJB里面可以改变session里面的内容
2013/06/05 面试题
yy婚礼主持词
2014/03/14 职场文书
5s标语大全
2014/06/23 职场文书
班组拓展活动方案
2014/08/14 职场文书
党的群众路线教育实践活动整改落实情况自查报告
2014/10/28 职场文书
90行Python代码开发个人云盘应用
2021/04/20 Python
每日六道java新手入门面试题,通往自由的道路
2021/06/30 Java/Android