我还没有找到一个权威的答案,尽管我有99.9%的把握这是真的。像被接受的答案这样的东西依赖于它是正确的,正如我期望的许多其他代码一样。但是,真正了解preg_match_all
的人(不是通过观察,而是通过特定的要求或特定的算法)能确认这是有保证的行为吗?我无法从文档中收集到它。
我的用例很简单:
preg_match_all("/$regexp/", $content, $matches, PREG_OFFSET_CAPTURE);
并且我知道$regexp
不包含任何子模式,因此文档告诉我$matches[0]
将是一个由2元素数组组成的数组,其中每个子数组具有具有数字键0的元素,其中包含匹配模式的字符串,数字键1包含匹配发生的$content
的偏移量。虽然数组元素通过增加偏移量来排序似乎是合理的,但我不知道哪里需要这样做,如果不是这样的话,这将是一个bug。虽然我无法想象它是如何做到有用的效果,也许有一些方法来实现preg_match_all
与多个线程附加他们的部分结果,而不合并成完全排序的顺序。
在我的特殊情况下,我只关心偏移量,而不是匹配的字符串,但偏移量增加是至关重要的。因此,带着腰带和吊带的心态,我编写:
preg_match_all("/$regexp/", $content, $matches, PREG_OFFSET_CAPTURE);
$offsets = array();
foreach ($matches as $match) {
$offsets[] = $match[1];
}
sort($offsets);
所以换句话说,最终的sort($offsets)
是保证浪费周期吗?
如果它不会让我陷入困境,问一个相关的,但潜在的单独的问题,如果排序是潜在的有用的,它会更多/更少/相同的效率采取默认的SORT_REGULAR
标志,如所示,或明确指定SORT_NUMERIC
,鉴于preg_match_all
内产生的偏移量必然是数字?
关于字符串偏移顺序的问题:
完整匹配应该始终按升序排列字符串偏移量。PHP通过设置start_offset
的循环实现全局匹配在最近一次完全匹配的末尾,直到主题字符串的末尾。也就是说,它先找到第一个匹配项,然后是第二个,然后第三个,以此类推。
如果您想验证我没有严重误读源代码(或遗漏重要内容),您可以查看函数ext/pcre/php_pcre.c
中的php_pcre_match_impl
。preg_match_all
将全局参数设置为1。是最后的一条评论把我引到了这里global
:
/*Advance to the position right after the last full match*/
start_offset = offsets[1];
如果设置了global,则循环以新的偏移量重复,并再次调用pcre_exec
。
关于SORT_NUMERIC问题:
这很难说。设置SORT_NUMERIC
使sort使用numeric_compare_function
进行元素比较,而SORT_REGULAR
使用compare_function
。
compare_function
进行类型检查,然后决定从那里进行比较,而numeric_compare_function
只是盲目地将两者转换为double
年代。由于两者都是long, compare_function
只是比较它们而不做任何类型的转换。因此,最终取决于哪个更快:是盲目地转换为double类型,还是执行类型检查。