正则表达式一个最重要的特性就是将匹配成功的模式的某部分进行存储供以后使用这一能力。
对一个正则表达式模式或部分模式两边添加圆括号将导致这部分表达式存储到一个临时缓冲区中。所捕获的每个子匹配都按照在正则表达式模式中从左至右所遇到的内容存储。存储子匹配的缓冲区编号从 1 开始,连续编号直至最大 99 个子表达式。每个缓冲区都可以使用 '\n' 访问,其中 n 为一个标识特定缓冲区的一位或两位十进制数。
可以使用非捕获元字符 '?:', '?=', or '?!' 来忽略对这部分正则表达式的保存。
测试代码:
[PHP] 纯文本查看 复制代码 <?php
$message = "GoogleGroadGroadMywenchang";
preg_match("/(Google)(Groad)\\2/", $message, $myarray);
echo "$myarray[0]";
?>
运行输出:这里,\2 指代的是 (Groad) 这个单元。
下面演示使用 ?: 的情况,将代码中的第二句修改如下:
[PHP] 纯文本查看 复制代码 <?php
$message = "GoogleGroadGroadMywenchang";
preg_match("/(?:Google)(Groad)\\1/", $message, $myarray);
echo "$myarray[0]";
echo "<br>";
echo "$myarray[1]";
echo "<br>";
echo "$myarray[2]";
?>
运行输出:由于忽略了 (Google) 这个单元,那么 (Groad) 这个单元的编号自然由 \1 来指代。从输出也可以看到,数组 myarray 中的第 2 个元素是空的。
?= 和 ?! ,是 “预测先行” 符。所谓 “预测先行” 表示从符号所匹配的内容(或不匹配的内容)的末端作为起始点搜索下一个正则匹配。这两者的区别是: ?= 是正向预测,而 ?! 是反向预测。“正向预测”是从正方向将匹配的内容的末端作为下一个正则的搜索起点,“反向预测”是从反方向将不匹配的内容的末端作为下一个正则的搜索的起点。
?= 示例用法:
[PHP] 纯文本查看 复制代码 <?php
$message = "12345GroadGroadGoogleGoogle";
preg_match("/(?=[0-9]*)Groad(Google)\\1/", $message, $myarray);
echo "$myarray[0]";
?>
运行输出:注意,上面的反向引用 \1 对应的是 (Google),而不是 ([0-9]),因为在它所在的括号里已经使用 ?= 表示该单元是个非捕获元。
?! 示例用法:
[PHP] 纯文本查看 复制代码 <?php
$message = "12345GroadGroadGoogleGoogle";
preg_match("/(?!Google)(Groad)\\1/", $message, $myarray);
echo "$myarray[0]";
?>
运行输出:$! 从字符串的末尾开始查找不匹配 Google 的起点,末尾刚好有 2 个 Google,因此它在查找时,找到了第一个 Google 后,接着继续预测是否还有第 2 个,还有,那么继续往下预测,直到没有发现匹配为止,然后就从那作为起点,开始匹配下一个正则,这里是 (Graod)\\1 。
再比较一个形式:
[PHP] 纯文本查看 复制代码 <?php
$message = "12345groadGoogleGroadGoogleGoogle";
preg_match("/(?!Google)groad/", $message, $myarray);
echo "$myarray[0]";
?>
运行输出:注意,要查找的字符串中有 3 个 Google 条目,而这个“预测”功能也是很好的发现了第 3 个 Google,尽管中间隔着一个 Groad 字串。 |