捕获和分组——迹忆客-ag捕鱼王app官网
分组和捕获
分组是将正则表达式中的一部分放在小括号()之内,从而将该部分组合在一起。分组内的正则表达式匹配的内容是连续的一个整体,比如说 /foot(ball)/ 可以也只能匹配football。和[]不同,[]里的正则不是连续的一个整体,比如/foot[ball]/ ,其中[ball]里面的每个字符是或的关系,它可以匹配的footb、foota、footl,如果再加上量词 /foot[ball] / 可以匹配foot后面跟着的b、a和l三个字符的任意组合。
下面回归到分组。分组内的正则是一个整体,如果想要可选分支,可以使用竖线|来实现。比如/foot(ball|age)/ 可以匹配 football或者footage。如果我们不使用(),则/football|age/ 只能匹配football或者 age。这就是分组的其中的一个作用。
分组的第二个作用就是捕获。在()中的正则匹配到的字符串会被保存起来,在正则表达式中可以继续引用这部分被捕获的字符串(反向引用)。被捕获的内容的下标从1开始计数。/foot(ball)/匹配字符串football 成功以后,下标0是整个正则表达式匹配到的内容,下标1是由()捕获的内容ball。对于下标的计数方式,遵循的原则是:嵌套从外到内,并列从左到右。什么意思呢,分组是可以嵌套的,如果正则中有分组嵌套分组的情形,那最外层的分组要先开始计数。并列的从左到右很好理解了,左边的要先于右边的。下面我们看/((foot|basket)(ball))/ 匹配字符串football。最外层的分组下标为1,内容是football,里层分组遵循从左至右原则,下标2为foot,下标3为ball。这里需要注意的是嵌套的优先级要高于并列的。就相当于深度遍历。如果一个分组1嵌套的有分组2,并且在分组1的右边并列又个分组3,则分组2的下标要先于分组3。/((foot|basket)(ball))\s(ok)/ 匹配字符串football ok,分组((foot|basket)(ball))的下标不会变,(ok)的下标是4。
执行结果
array
(
[0] => football ok
[1] => football
[2] => foot
[3] => ball
[4] => ok
)
注: 捕获分组的最大下标序号是65535,也就是说最大可以有65535个分组。然而现实中我们不会在一个正则表达式中使用这么多的分组。
既然分组可以对分组内匹配到的字符串进行捕获,那如果我们仅仅是对正则进行分组,而不对其捕获,这也是可以的。非捕获分组形式为(?:)。对于上面的例子,如果不想捕获football,可以修改正则为/(?:(foot|basket)(ball))\s(ok)/
再看执行结果 football 就不会被捕获了。
array
(
[0] => football ok
[1] => foot
[2] => ball
[3] => ok
)
在php中,对于分组(不管是捕获还是非捕获),还提供了另一种功能。可以给分组单独指定模式修饰符。在分组的开始部分加上(?修饰符)。 捕获分组形式((?修饰符)regex);非捕获分组形式(?:(?修饰符)regex)。 对于非捕获分组还有另一种形式,就是在 ? 和 : 之间加修饰符——(?修饰符:)。 例如让foot或者basket不区分大小写,/(((?i)foot|basket)(ball))\s(ok)/。
匹配结果
array
(
[0] => football ok
[1] => football
[2] => foot
[3] => ball
[4] => ok
)
非捕获两种形式
执行结果
array
(
[0] => football ok
[1] => football
[2] => ball
[3] => ok
)
捕获内容的命名
对于捕获的内容除了使用下标进行索引之外,php还提供了给捕获命名的功能。语法形式为(?) 或者(?'name')。
/((?foot|basket)(ball))\s(ok)/ 给分组命名为type。那么除了对捕获的内容进行下标索引之外,还能使用键名进行关联。
foot|basket)(ball))\s(ok)/";
$res = preg_match($pattern,$str,$matches);
print_r($matches);
执行结果
array
(
[0] => football ok
[1] => football
[type] => foot
[2] => foot
[3] => ball
[4] => ok
)
查看笔记