🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 分组 **分组()** 匿名分组:`(partten)` 上面说过重复一个字符0次、一次或多次,那么如何重复多个字符呢,就是我们要说的分组,例如要匹配一段IP地址(简单的IP匹配):(/d{1,3}/.){3}/d{1,3}.其中()括起来的部分重复3次。 分组时指定组名: ``` <pre class="calibre10">``` <span class="token3">(</span><span class="token1">?</span><span class="token1"><</span>group<span class="token1">></span>parttern<span class="token3">)</span> <span class="token3">(</span><span class="token1">?</span><span class="token2">'groupname'</span>parttern<span class="token3">)</span> <span class="token3">(</span><span class="token1">?</span>P<span class="token1"><</span>groupname<span class="token1">></span>parttern<span class="token3">)</span> ``` ``` 例子: ``` <pre class="calibre10">``` $subject<span class="token1">=</span><span class="token2">"AAABBCCAAAADDE666FF"</span><span class="token3">;</span> $pattern<span class="token1">=</span><span class="token2">"/(\w)/"</span><span class="token3">;</span> <span class="token">//匿名分组</span> $pattern<span class="token1">=</span><span class="token2">"/(?<name>\w)/"</span><span class="token3">;</span> $pattern<span class="token1">=</span><span class="token2">"/(?P<name>\w)/"</span><span class="token3">;</span> $pattern<span class="token1">=</span><span class="token2">"/(?'name'\w)/"</span><span class="token3">;</span> <span class="token">//只能单引号</span> $a<span class="token1">=</span><span class="token4">preg_match_all</span><span class="token3">(</span>$pattern<span class="token3">,</span> $subject<span class="token3">,</span> $matches<span class="token3">,</span> PREG_OFFSET_CAPTURE<span class="token3">)</span><span class="token3">;</span> <span class="token4">dump</span><span class="token3">(</span>$matches<span class="token3">)</span><span class="token3">;</span> ``` ``` ``` <pre class="calibre10">``` $subject<span class="token1">=</span>" PDO<span class="token3">:</span><span class="token3">:</span><span class="token4">ATTR_TIMEOUT</span><span class="token3">(</span>integer<span class="token3">)</span> 设置连接数据库的超时秒数。 PDO<span class="token3">:</span><span class="token3">:</span><span class="token4">ATTR_ERRMODE</span><span class="token3">(</span>integer<span class="token3">)</span> 关于此属性的更多信息请参见 错误及错误处理 部分。"<span class="token3">;</span> $pattern<span class="token1">=</span><span class="token2">"/(?P<pdo>PDO)::(?P<pro>[^)(]+)+\((?P<type>[^)(]+)+\)\s+(?P<desc>[^\r\n]+)/"</span><span class="token3">;</span> <span class="token4">preg_match_all</span><span class="token3">(</span>$pattern<span class="token3">,</span>$subject <span class="token3">,</span>$matches<span class="token3">)</span><span class="token3">;</span> ``` ``` **组名的反向引用** 表达式在匹配时,表达式引擎会将小括号 "( )" 包含的表达式所匹配到的字符串记录下来。在获取匹配结果的时候,小括号包含的表达式所匹配到的字符串可以单独获取引用方法是 "\\" 加上一个数字。"\\1" 引用第1对括号内匹配到的字符串,"\\2" 引用第2对括号内匹配到的字符串……以此类推,如果一对括号内包含另一对括号,则外层的括号先排序号。换句话说,哪一对的左括号 "(" 在前,那这一对就先排序号 反向引用 说明 **\\n** 对指定数字编号的分组进行反向引用 **\\g<name>** 对指定名字的命名分组进行反向引用 **\\k<name>** **\\k'name'** ## 从一个简单例子说起 ``` <pre class="calibre10">``` $subject<span class="token1">=</span><span class="token2">"abcdebbcde"</span><span class="token3">;</span> $pattern<span class="token1">=</span><span class="token2">"/([ab])\\1/"</span><span class="token3">;</span> <span class="token">// 注意php的\\1前还需要加个\转义"\"</span> 等同 $pattern<span class="token1">=</span><span class="token2">"/([ab])([ab])/"</span><span class="token3">;</span> ``` ``` 对于正则表达式“**(\[ab\])\\1**”,捕获组中的子表达式“**\[ab\]**”虽然可以匹配“**a**”或者“**b**”,但是捕获组一旦匹配成功,反向引用的内容也就确定了。如果捕获组匹配到“**a**”,那么反向引用也就只能匹配“**a**”,同理,如果捕获组匹配到的是“**b**”,那么反向引用也就只能匹配“**b**”。由于后面反向引用“**\\1**”的限制,要求必须是两个相同的字符,在这里也就是“**aa**”或者“**bb**”才能匹配成功。 考察一下这个正则表达式的匹配过程,在位置0处,由“**(\[ab\])**”匹配“**a**”成功,将捕获的内容保存在编号为1的组中,然后把控制权交给“**\\1**”,由于此时捕获组已记录了捕获内容为“**a**”,“**\\1**”也就确定只有匹配到“**a**”才能匹配成功,这里显然不满足,“**\\1**”匹配失败,由于没有可供回溯的状态,整个表达式在位置0处匹配失败。 正则引擎向前传动,在位置5之前,“**(\[ab\])**”一直匹配失败。传动到位置5处时,,“**(\[ab\])**”匹配到“**b**”,匹配成功,将捕获的内容保存在编号为1的组中,然后把控制权交给“**\\1**”,由于此时捕获组已记录了捕获内容为“**b**”,“**\\1**”也就确定只有匹配到“**b**”才能匹配成功,满足条件,“**\\1**”匹配成功,整个表达式匹配成功,匹配结果为“**bb**”,匹配开始位置为5,结束位置为7。 扩展一下,正则表达式“**(\[a-z\])\\1{2}**”也就表达连续三个相同的小写字母。 ``` <pre class="calibre10">``` $subject<span class="token1">=</span><span class="token2">"abc 123abcd"</span><span class="token3">;</span> $pattern<span class="token1">=</span><span class="token2">"/(abc)(\s)(\d)+?\\1/"</span><span class="token3">;</span><span class="token">//\1就是第一个()组匹配到的内容 注意需要将\转义下</span> $a<span class="token1">=</span><span class="token4">preg_match_all</span><span class="token3">(</span>$pattern<span class="token3">,</span> $subject<span class="token3">,</span> $matches<span class="token3">,</span> PREG_OFFSET_CAPTURE<span class="token3">)</span><span class="token3">;</span> <span class="token4">var_export</span><span class="token3">(</span>$matches<span class="token3">)</span><span class="token3">;</span><span class="token">//匹配到abc 123abc</span> ``` ``` 更多反向引用实例 ``` <pre class="calibre10">``` $subject<span class="token1">=</span><span class="token2">"AAABBCCAAAADDE666FF"</span><span class="token3">;</span> $pattern<span class="token1">=</span><span class="token2">"/(\w)/"</span><span class="token3">;</span> $a<span class="token1">=</span><span class="token4">preg_match_all</span><span class="token3">(</span>$pattern<span class="token3">,</span> $subject<span class="token3">,</span> $matches<span class="token3">,</span> PREG_OFFSET_CAPTURE<span class="token3">)</span><span class="token3">;</span> <span class="token4">var_export</span><span class="token3">(</span>$matches<span class="token3">)</span><span class="token3">;</span> <span class="token">//['A','A','A','B','B','C','C','A','A','A','A','D','D','E','6','6','6','F','F';</span> $pattern<span class="token1">=</span><span class="token2">"/(\w)\\1/"</span><span class="token3">;</span> <span class="token">//array ( 'AA', 'BB', 'CC','AA', 'AA', 'DD', '66','FF',)</span> $pattern<span class="token1">=</span><span class="token2">"/(\w)\\1*/"</span><span class="token3">;</span> <span class="token">//[ 'AAA', 'BB', 'CC', 'AAAA', 'DD', 'E', '666', 'FF' ]</span> $pattern<span class="token1">=</span><span class="token2">"/(\w)+/"</span><span class="token3">;</span> <span class="token">//[ 'AAA', 'BB', 'CC', 'AAAA', 'DD', '666', 'FF' ]</span> $pattern<span class="token1">=</span><span class="token2">"/(\w)(\d)/"</span><span class="token3">;</span> <span class="token">//[ 'E6', '66' ]</span> $pattern<span class="token1">=</span><span class="token2">"/(\w)(\d)\\1/"</span><span class="token3">;</span> <span class="token">//array ( '666')</span> $pattern<span class="token1">=</span><span class="token2">"/(\w)(\d)\\1*/"</span><span class="token3">;</span> <span class="token">//[ 'E6', '66' ]</span> $pattern<span class="token1">=</span><span class="token2">"/(\w)(\d)\\1+/"</span><span class="token3">;</span> <span class="token">//[ '666' ]</span> $pattern<span class="token1">=</span><span class="token2">"/(\w)(\d)\\1\\2*/"</span><span class="token3">;</span> <span class="token">//[ 'E666' ]</span> $pattern<span class="token1">=</span><span class="token2">"/(\w)(\d)\\1\\2+/"</span><span class="token3">;</span> <span class="token">//[ 'E666' ]</span> ``` ``` ``` <pre class="calibre17">``` $subject<span class="token1">=</span><span class="token2">"aaa bbbb ffffff 999999999"</span><span class="token3">;</span> $pattern<span class="token1">=</span><span class="token2">"/(\w)((?=\\1\\1\\1)(\\1))+/"</span><span class="token3">;</span> $a<span class="token1">=</span><span class="token4">preg_match_all</span><span class="token3">(</span>$pattern<span class="token3">,</span> $subject<span class="token3">,</span> $matches<span class="token3">)</span><span class="token3">;</span> <span class="token4">var_export</span><span class="token3">(</span>$matches<span class="token3">)</span><span class="token3">;</span> # <span class="token3">[</span> <span class="token2">'bb'</span><span class="token3">,</span> <span class="token2">'ffff'</span><span class="token3">,</span> <span class="token2">'9999999'</span><span class="token3">]</span> # <span class="token3">(</span><span class="token1">?</span><span class="token1">=</span>exp<span class="token3">)</span>非获取匹配的正向肯定预查 匹配\<span class="token6">1</span>\<span class="token6">1</span>\<span class="token6">1</span>左边的\w 而\<span class="token6">1</span> 又是第一个\w \<span class="token6">1</span>\<span class="token6">1</span>\<span class="token6">1</span>可知至少三个相同的\w字符 后面的<span class="token3">(</span>\\<span class="token6">1</span><span class="token3">)</span><span class="token1">+</span>可知至少一个 # <span class="token3">(</span>\w<span class="token3">)</span><span class="token3">(</span><span class="token3">(</span><span class="token1">?</span><span class="token1">=</span>\\<span class="token6">1</span>\\<span class="token6">1</span>\\<span class="token6">1</span><span class="token3">)</span> 三个相同的\w字左边还有一个相同的\为字符 即符四个相同的\w字符 # ``` ```