preg_match在第一个选择器中选择匹配

时间:2013-03-19 16:53:16

标签: php regex

我有这个字符串要测试,无法让它按照我想要的方式工作:

<?php
$string = '500 or fatal error ?';
$regex = '#(fatal|500)#';
if (preg_match($regex, $string, $return)) {
    // Return 500
    echo $return[1];
}
?>

我希望我的脚本返回致命而不是500,因为它是我的第一个选择器。 有可能吗?

先谢谢,对不起我的英语很差。

P.S。 :也许我的标题不是很清楚,但我不知道如何更好地解释它。如果找到它,请更改它。

3 个答案:

答案 0 :(得分:2)

有两种正则表达式引擎:text-directed enginesregex-directed引擎。

php是regex-directed引擎,它总会返回最左边的匹配,即使以后可以找到“500”匹配

  

引擎将从字符串的第一个字符开始。它会   首先尝试所有可能的正则表达式排列   字符。只有所有可能性都经过了尝试和发现   失败,引擎会继续使用文本中的第二个字符。   同样,它将完全尝试正则表达式的所有可能的排列   相同的订单。结果是正则表达式引擎会   返回最左边的比赛。

您可以找到更多信息here

答案 1 :(得分:2)

这不可能像你想象的那样,但是一个不同的实现将使它工作

$string = '500 or fatal error';
$regexes = array('#\bfatal\b#', '#\b500\b#');

$match = null;
foreach ($regexes as $re)
  if (preg_match($re, $string, $match))
    break;
# $match is null -> not found

答案 2 :(得分:2)

如果你想只用一个正则表达式,你可以这样做:

$selectors = array( 'fatal', '500'); // Array of selectors (in priority order)

$delimiter = '/';
$regex = $delimiter . '(' . implode('|', array_map( 'preg_quote', $selectors, array_fill( 0, count( $selectors), '/'))) . ')' . $delimiter;
preg_match_all( $regex, $string, $matches);

按照数组的顺序查看我们找到的选择器:

$found_selectors = array_flip( $matches[1]);
foreach( $selectors as $selector) { 
    if( isset( $found_selectors[$selector])) 
        return $selector;
}

请注意,我翻转了$matches[1]数组,以便在数组中获得恒定的查找时间,而不是执行array_search() / in_array(),这将进行线性搜索。

根据您的输入字符串,您可以从this demo看到这会产生fatal