熟练掌握正则表达式是每个程序员的基础要求,对于每个初学者来说会被正则表达式一连串字符弄得头晕眼花。博主便会如此,一直对正则表达式有种莫名的恐惧。近来看到另一位博友写的 《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个。

最新文章

  1. ubuntu 下安装scrapy
  2. (利用tempdata判断action是直接被访问还是重定向访问)防止微信活动中用户绕过关注公众号的环节
  3. c# GridView有关RowClick事件,可单击显示选中的row
  4. centos yum 使用笔记
  5. windows下nginx和php环境的配置
  6. oracle 11g 表空间使用率
  7. 我们为什么要使用 href=&quot;javascript:void(0)&quot;
  8. [jobdu]孩子们的游戏(圆圈中最后剩下的数)
  9. All in All
  10. Tsinsen-A1488 : 魔法波【高斯消元+异或方程组】
  11. Ajax+存储过程真分页实例解析(10W数据毫秒级+项目解析)
  12. jsp中EL表达式不起作用的问题1
  13. mysql中cast() 和convert()的用法讲解
  14. 初识Python.day2
  15. Android 最流行的吸顶效果的实现及代码
  16. Git push 时如何避免出现 &quot;Merge branch &#39;master&#39; of ...&quot;
  17. py-day2 python 列表
  18. golang--性能测试和分析
  19. 小记 百度地图 soso地图 经纬度偏移
  20. poj-2777线段树刷题

热门文章

  1. mongo学习笔记(五):分片
  2. web前端开发教程系列-2 - 前端开发书籍分享(转)
  3. 使用MongoDB C#官方驱动操作MongoDB
  4. 第十章 MySQL 常用函数
  5. 获取tomcat上properties文件的内容——方便文件存储位置的修改,解耦和
  6. SQL Server with(nolock)详解
  7. iTOP-4412开发板低功耗高性能的开源硬件平台——上手评测
  8. Codeforces Zepto Code Rush 2014 -C - Dungeons and Candies
  9. 第11章 Windows线程池(1)_传统的Windows线程池
  10. 解决-bash: lsb_release: command not found