preg_offset_capture子数组的顺序是否*保证*递增偏移量


Is the order of a preg_offset_capture sub-array *guaranteed* to be increasing offset?

我还没有找到一个权威的答案,尽管我有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_implpreg_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类型,还是执行类型检查。