没有编号数组的 PHP 子模式


PHP Subpattern without Numbering Array

preg_match与子模式一起使用总是返回具有相同数据的双键数组,一个带有子模式名称,另一个带有数字标记。因为我匹配的是数十万行,每行只有几千字节,所以恐怕数字数组占用了额外的内存。有没有正确的方法可以禁止数字标签数组返回?

例:

<?php
header('Content-Type: text/plain');
$data = <<<START
I go to school.
He goes to funeral.
START;
preg_match_all('@^(?<who>.*?) go(es)* to (?<place>.*?)$@m', $data, $matches);
print_r($matches);
?>

输出:

Array
(
    [0] => Array
        (
            [0] => I go to school.
            [1] => He goes to funeral.
        )
    [who] => Array
        (
            [0] => I
            [1] => He
        )
    [1] => Array
        (
            [0] => I
            [1] => He
        )
    [2] => Array
        (
            [0] => 
            [1] => es
        )
    [place] => Array
        (
            [0] => school.
            [1] => funeral.
        )
    [3] => Array
        (
            [0] => school.
            [1] => funeral.
        )
)

from php.net- subpatterns

可以使用语法命名子模式 (?P<name>pattern) 。然后,此子模式将在匹配数组中按其正常数字位置和名称进行索引。

我没有看到仅按名称提供索引的选项。

所以,我认为,如果你不想要这些数据两次,唯一的可能性是:不要使用命名组。

这真的是一个问题吗?IMO 仅在遇到问题时才优化此功能,因为这种额外的内存使用量!改进的可读性应该值得记住!

更新

看起来go(es)*应该只匹配可选的"es"。在这里,您可以使用非捕获组来节省内存。

preg_match_all('@^(?<who>.*?) go(?:es)? to (?<place>.*?)$@m', $data, $matches);

通过以?:启动组,则不会存储匹配的内容。我还替换了表示 0 或更多的*,并且还将"goeseses"与表示 0 或 1 的 ? 匹配。