PHP preg_match_all $ matches输出包含3行

时间:2014-04-22 02:47:59

标签: php regex preg-match-all

这是我的测试代码:

$test = '@12345 abc @12 @abd engng@geneng';
preg_match_all('/(^|\s)@([^@ ]+)/', $test, $matches);
print_r($matches);

输出$matches

Array ( [0] => Array ( [0] => @12345 [1] => @12 [2] => @abd ) [1] => Array ( [0] => [1] => [2] => ) [2] => Array ( [0] => 12345 [1] => 12 [2] => abd ) )

我的问题是为什么它有一个空行?

[1] => Array ( [0] => [1] => [2] => )

如果我在(^|\s)中乘坐regex,第二行将会消失。但是,我无法阻止匹配@geneng

任何答案都将不胜感激。

4 个答案:

答案 0 :(得分:2)

正则表达式的问题在于它匹配@,即使它前面有空格。因为\s将匹配空格,所以它将被捕获到$matches数组中。您可以使用lookarounds解决此问题。在这种情况下,它可以通过积极的观察来解决:

preg_match_all('/(?<=^|\s)@([^@ ]+)/', $test, $matches);

这将匹配@ 之后的部分(如果它前面有空格或行首锚点)。重要的是要注意,lookarounds实际上并不消耗字符。他们只断言给定的正则表达式是在其后面或之前。

Demo

答案 1 :(得分:1)

这是因为要测试(^|\s)的内存捕获:

preg_match_all('/(^|\s)@([^@ ]+)/', $test, $matches);
                 ^^^^^^

它被捕获为内存位置#1,所以为了避免你可以简单地使用非捕获括号:

preg_match_all('/(?:^|\s)@([^@ ]+)/', $test, $matches);
                  ^^

答案 2 :(得分:0)

preg_match_all默认使用PREG_PATTERN_ORDER标志。这意味着您将获得:

$matches[0] -> all substrings that matches the whole pattern
$matches[1] -> all capture groups 1
$matches[2] -> all capture groups 2
etc.

您可以使用PREG_SET_ORDER标志更改此行为:

$matches[0] -> array with the whole pattern and the capture groups for the first result
$matches[1] -> same for the second result
$matches[2] -> etc.

在您的代码中(默认为PREG_PATTERN_ORDER),您只获得$ matches [1],只包含空或空白项目,因为它是捕获组1的内容(^|\s)

答案 3 :(得分:0)

有两组括号,这就是为什么你得到一个空行。 PHP认为,你想要在字符串中有2组匹配。删除其中一个将删除一个阵列。

仅供参考:在这种情况下,您不能使用[^ | \ s]而不是(^ | \ s)。因为PHP会想,你要排除空格。