php preg_match_all 需要多个结果

php preg_match_all need multiple results

我想要 preg_match_all 到 return 它找到的所有模式,即使结果已经被使用。下面的示例隔离了问题。

$str = "whatever aaa 34567 aaa 56789 ll";
$pattern = '/.{0,100}\D[aaa]{3}\D{1}[0-9]{5}\D{1}/';
preg_match_all($pattern, $str, $amatches);
var_dump($amatches);

以上return个数组元素的结果。

0=>    `whatever aaa 34567 aaa 56789 `

我要的是2个数组元素。

0=>    `whatever aaa 34567`   
1=>    `whatever aaa 34567 aaa 56789`  

这个更近一点:

$str = "whatever aaa 34567 aaa 56789 ll";
$pattern = '/^((.*)\D[aaa]{3}\D{1}[0-9]{5}\D{1})?/';
preg_match($pattern, $str, $amatches);
var_dump($amatches);

returns

 array(3) { 
        [0] => string(29) "whatever aaa 34567 aaa 56789 " 
        [1] => string(29) "whatever aaa 34567 aaa 56789 " 
        [2] => string(18) "whatever aaa 34567" 
    }

或者这仍然使用 preg_match_all:

$str = "whatever aaa 34567 aaa 56789 ll";
$pattern = '/^((.*)\D[aaa]{3}\D{1}[0-9]{5}\D{1})?/';
preg_match_all($pattern, $str, $amatches);
var_dump($amatches);

我认为正在发生的事情是您的 .{0,100} 正在被通读整个内容,而根本不允许正则表达式在最后启动。这 ?确保它以您的模式结尾。

这是使用 preg_replace_callback 完成这项工作的替代解决方案。

  • 查找匹配 "any characters followed by (and including) three 'a' characters, some space and five digits" 的字符串。可能有尾随空格。 \b 表示单词边界,防止匹配 "xaaa 12345"、"aaa 123456" 或 "aaa 12345xyz"
  • 将匹配字符串连接到 $soFar,其中包含任何先前匹配的字符串
  • 将该字符串附加到 $result 数组

我不太确定你是否希望 "foo"s 和 "bar"s 保留在字符串中,所以我把它们留在了。

$str = "whatever foo aaa 12345 bar aaa 34567 aaa 56789 baz fez";

preg_replace_callback(
    '/.*?\baaa +\d{5}\b\s*/',
    function ($matches) use (&$result, &$soFar) {
        $soFar .= $matches[0];
        $result[] = trim($soFar);
    }, $str
);
print_r($result);

输出:

Array
(
    [0] => whatever foo aaa 12345 
    [1] => whatever foo aaa 12345 bar aaa 34567 
    [2] => whatever foo aaa 12345 bar aaa 34567 aaa 56789 
)

使用 preg_match_all and array_map 的两步版本:

preg_match_all('/.*?\baaa +\d{5}\b\s*/', $str, $matches);
$matches = array_map(
    function ($match) use (&$soFar) {
        $soFar .= $match;
        return trim($soFar);
    },
    $matches[0]
);
print_r($matches);