PHP之正则表达式捕获组与非捕获组(详解)

在项目开发过程中正则表示经常会用到,可以说会正则表达式是每个程序员最基本的要求,初学者在刚接触正则表达式都感到很吃力。最近看到一位朋友的博客写的《PHP正则表达式》获益颇多,在章节对通配符以及捕获数据非常感兴趣。这两章节刚好也涉及到了正则表达式的捕获组和非捕获组的内容,以此来分析这方面的内容

  我们知道,在正则表达式下(x) 表示匹配'x'并记录匹配的值。这只是比较通俗的说法,甚至说这是不严谨的说法,只有()捕获组形式才会记录匹配的值。非捕获组则只匹配,不记录。

  捕获组:

  (pattern)

这种形式是我们见到最多的一种形式,匹配并返回捕获结果,可以嵌套,组号顺序从左到右依次排列‘。

代码如下:

$regex = '/(ab(c)+)+d(e)?/';   
$str = 'abccde';
$matches = array();
 
if(preg_match($regex, $str, $matches)){
    print_r($matches);
}

  匹配结果:

代码如下:

Array ( [0] => abccde [1] => abcc [2] => c [3] => e )
  (?P<name>pattern)

这种方式虽然看起来在构造正则表达式的时候略微复杂一点,但实质上与(pattern)一样。最大的优势体现在对结果处理上,程序员可以直接根据自己设置的<name>直接快速调用结果,而不用再去数需要的结果在第几个子组了。

代码如下:

$regex = '/(?P<group1>\w(?P<group2>\w))abc(?P<group3>\w)45/';

$str = 'fsabcd45';
$matches = array();
 
if(preg_match($regex, $str, $matches)){
    print_r($matches);
}

  匹配结果:

代码如下:

Array ( [0] => fsabcd45 [group1] => fs [1] => fs [group2] => s [2] => s [group3] => d [3] => d )
  \num

num是一个整数,是对捕获组的反向引用。  例如\2表示第二个子组匹配值,\表示第一个子组匹配值

代码如下:

$regex = '/(\w)(\w)\2\1/';   
$str = 'abba';
$matches = array();
 
if(preg_match($regex, $str, $matches)){
    print_r($matches);
}

  匹配结果:

代码如下:

Array ( [0] => abba [1] => a [2] => b )

注意,这里我疏忽了一个小细节,一开始我第一样代码是 $regex = “/(\w)(\w)\2\1/”;  结果返回无匹配结果,经过调试后,发现这里只能用' '。'与" 用法差别大家还是需要注意下。

  \k< name >

  了解了(?P<name>pattern)与\num,这个就不难理解了。\k< name >是对命名捕获组的反向引用。其中 name 是捕获组名。

代码如下:

$regex='/(?P<name>\w)abc\k<name>/';

$str="fabcf";

echo preg_match_all($regex, $str,$matches);

print_r($matches);

  匹配结果:

代码如下:

Array ( [0] => Array ( [0] => fabcf ) [name] => Array ( [0] => f ) [1] => Array ( [0] => f ) )

  非捕获组:

  (?:pattern)

  与(pattern)的唯一区别是,匹配pattern但不捕获匹配结果。这里便不再举例。

  还有四种方式实际上讲的是一个事情:预查。

  预查分为正向预查与反向预查。根据字面理解,正向预查是判断匹配字符串后面某些字符存在与否,而反向预查则是判断匹配字符串前面某些字符存在与否。

  正向预查判断存在使用(?=pattern),判断不存在使用(?!pattern)。

  反向预查判断存在使用(?<=pattern),判断不存在使用(?<!pattern)。

代码如下:

$regx='/(?<=a)bc(?=d)/';

$str="abcd ebcd abce ebca";

if(preg_match_all($regx, $str, $matches)){

print_r($matches);
}

  匹配结果:

代码如下:

Array ( [0] => Array ( [0] => bc) )

  这四种形式使用的是否只要注意好相对匹配字符串的位置和断言肯定还是否定,就会很快掌握。

  另外,预查的四种形式是零宽度的,匹配的时候只做一个判断,本身是不占位置的。/HE(?=L)LLO/ 与HELLO匹配,而/HE(?=L)LO/与HELLO是不匹配的。毕竟但从字节数上两者就是不匹配的,前者只有4个,而后者有5个。

以上就是PHP之正则表达式捕获组与非捕获组详解的全部内容,希望对大家有所启迪。

(0)

相关推荐

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

    今天遇到一个正则匹配的问题,忽然翻到有捕获组的概念,手册上也是一略而过,百度时无意翻到C#和Java中有对正则捕获组的特殊用法,搜索关键词有PHP时竟然没有相关内容,自己试了一下,发现在PHP中也是可行的,于是总结一下,分享的同时也希望有大神和细心的学习者找到我理解中出现的问题. 什么是捕获组 捕获组语法: 字符  描述 示例 (pattern) 匹配pattern并捕获结果,自动设置组号. (abc)+d 匹配abcd或者abcabcd (?<name>pattern) 或 (?'name'

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

    今天遇到一个正则匹配的问题,忽然翻到有捕获组的概念,手册上也是一略而过,百度时无意翻到C#和Java中有对正则捕获组的特殊用法,搜索关键词有PHP时竟然没有相关内容,自己试了一下,发现在PHP中也是可行的,于是总结一下,分享的同时也希望有大神和细心的学习者找到我理解中出现的问题. 什么是捕获组 我们先看一下PHP的正则匹配函数 int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags =

  • 正则表达式之 贪婪与非贪婪模式详解(概述)

    1 概述 贪婪与非贪婪模式影响的是被量词修饰的子表达式的匹配行为,贪婪模式在整个表达式匹配成功的前提下,尽可能多的匹配,而非贪婪模式在整个表达式匹配成功的前提下,尽可能少的匹配.非贪婪模式只被部分NFA引擎所支持. 属于贪婪模式的量词,也叫做匹配优先量词,包括: "{m,n}"."{m,}"."?"."*"和"+". 在一些使用NFA引擎的语言中,在匹配优先量词后加上"?",即变成属于非

  • PHP之正则表达式捕获组与非捕获组(详解)

    在项目开发过程中正则表示经常会用到,可以说会正则表达式是每个程序员最基本的要求,初学者在刚接触正则表达式都感到很吃力.最近看到一位朋友的博客写的<PHP正则表达式>获益颇多,在章节对通配符以及捕获数据非常感兴趣.这两章节刚好也涉及到了正则表达式的捕获组和非捕获组的内容,以此来分析这方面的内容 我们知道,在正则表达式下(x) 表示匹配'x'并记录匹配的值.这只是比较通俗的说法,甚至说这是不严谨的说法,只有()捕获组形式才会记录匹配的值.非捕获组则只匹配,不记录. 捕获组: (pattern) 这

  • js正则表达式之前瞻后顾与非捕获分组

    目录 前瞻后顾与捕获分组的结合使用 捕获分组与非捕获分组 前瞻.后顾与负前瞻.负后顾 总结 前瞻后顾与捕获分组的结合使用 在现实的应用场景中,捕获分组或非捕获分组通常被限制在前瞻后顾条件内,举例来说,对数字12345678格式化,结果为12,345,678.其正则实现如下: let formatSum = '12345678'.replace(/\B(?=(?:\d{3})+(?!\d))/g, ',') 捕获分组与非捕获分组 为了理解前瞻与后顾,首先要先理解捕获分组与非捕获分组 在js中, (

  • Python正则表达式中group与groups的用法详解

    目录 1 .group函数 1.1 返回整个匹配结果 1.2 返回指定分组的匹配结果 1.3 处理没有匹配结果的情况 2. groups函数 3. group和groups的使用场景 在Python中,正则表达式的group和groups方法是非常有用的函数,用于处理匹配结果的分组信息.group方法是re.MatchObject类中的一个函数,用于返回匹配对象的整个匹配结果或特定的分组匹配结果.而groups方法同样是re.MatchObject类中的函数,它返回的是所有分组匹配结果组成的元组

  • python re模块匹配贪婪和非贪婪模式详解

    这篇文章主要介绍了python re模块匹配贪婪和非贪婪模式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 python贪婪和非贪婪 正则表达式通常用于在文本中查找匹配的字符串.Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符:非贪婪则相反,总是尝试匹配尽可能少的字符.在"*","?","+","{m,n}"后面加上?,使贪婪

  • python正则表达式中匹配次数与贪心问题详解(+ ?*)

    python中正则表达式中的匹配次数问题网上有很多解释,最多的就是*匹配0或者无数次,+匹配1次或无数次,?匹配0次或者1次.可是虽然这个文字描述很简单,但是真正用起来的时候大家有没有发觉还是需要谨慎使用才能发挥出这个匹配次数的真正功能,下面举几个简单例子参考: 首先是一个很简单的匹配: 字符串如下 我们直接匹配python,结果只匹配到一个 接下来我们把匹配次数的符号加进去,首先是*,结果如下: 匹配到了三处,即匹配到了所有的前缀有python的字符串 换成+再次匹配 结果和*的匹配一致,那使

  • java 中同步、异步、阻塞和非阻塞区别详解

    java 中同步.异步.阻塞和非阻塞区别详解 简单点说: 阻塞就是干不完不准回来,一直处于等待中,直到事情处理完成才返回: 非阻塞就是你先干,我先看看有其他事没有,一发现事情被卡住,马上报告领导. 我们拿最常用的send和recv两个函数来说吧... 比如你调用send函数发送一定的Byte,在系统内部send做的工作其实只是把数据传输(Copy)到TCP/IP协议栈的输出缓冲区,它执行成功并不代表数据已经成功的发送出去了,如果TCP/IP协议栈没有足够的可用缓冲区来保存你Copy过来的数据的话

  • 逻辑表达式中与或非的用法详解

    先说逻辑与(&&),它可以从三个层次进行理解 第一个层次最简单,就是简单的布尔值之间的逻辑与,就是左值和右值都是true时,返回true,两边都是false或者两边的值其中一边是fasle,就返回false:(AND操作): 第二个层次,(false,null,indefined,0,-0,NaN和""这些都是假值,其他所有的值包括对象都是真值),对这些"真值"和"假值"进行AND操作,返回一个"真值"或者&q

  • java 线程公平锁与非公平锁详解及实例代码

    java 线程公平锁与非公平锁详解 在ReentrantLock中很明显可以看到其中同步包括两种,分别是公平的FairSync和非公平的NonfairSync.公平锁的作用就是严格按照线程启动的顺序来执行的,不允许其他线程插队执行的:而非公平锁是允许插队的. 默认情况下ReentrantLock是通过非公平锁来进行同步的,包括synchronized关键字都是如此,因为这样性能会更好.因为从线程进入了RUNNABLE状态,可以执行开始,到实际线程执行是要比较久的时间的.而且,在一个锁释放之后,其

随机推荐