2013-03-19 36 views
3

我有这样的字符串进行测试,因此无法管理,使其工程,我想:的preg_match在第一选择中选择匹配

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

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

感谢提前,并为我可怜的英语感到抱歉。

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

+0

我不知道,如果正则表达式在这里合适的工具,因为它们会读字符串由左到右。 – 2013-03-19 16:55:03

+0

好,第一场比赛是'500',在你的正则表达式匹配这里从字符串的开头,以便开始没有什么区别 – 2013-03-19 16:55:10

+0

@MarkoD是否有可能改变这种行为? – 2013-03-19 16:56:32

回答

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,给定您的输入字符串。

+0

哇!它看起来像我想要的那样工作。我正在看它看看它是如何工作的,非常感谢! – 2013-03-19 17:14:12

+0

我查看了一下解释,但'$ regex'只是形成一个动态正则表达式,除非我使用'$ selectors'数组并确保使用'preg_quote()正确地转义所有选择器“ '。然后,就像你之前所做的那样,你在'$ matches [1]'中得到一个数组,我只是翻转数组,然后迭代'$ selectors'(按优先级顺序)来查看哪一个(如果有的话)被发现在字符串中。找到的第一个,得到回报。 – nickb 2013-03-19 17:15:41

+0

这就是我所看到的。花点时间理解一切。完美的逻辑,谢谢! – 2013-03-19 17:16:51

2

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

PHP是regex-directed引擎,它总是返回最左边的匹配,即使“500”比赛以后可以

发现该发动机将在字符串的第一个字符开始。它会 尝试在第一个 字符的正则表达式的所有可能的排列。只有在所有可能性都被尝试并发现 失败的情况下,引擎才会继续显示文本中的第二个字符。 再一次,它会尝试正则表达式的所有可能的排列,正好在 相同的顺序。结果是,正则表达式引擎 返回最左边的匹配。

你可以找到更多信息here

+0

感谢您的解释。我认为这是不可能强制PHP作为文本引导引擎行事? – 2013-03-19 17:05:50

+1

@Tririus不,你不能强迫它到文本引导引擎 – Anirudha 2013-03-19 17:07:36

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 
+1

这也需要对'n'选择器进行'n' regexes和'n'评估,其中OP有150个,这可能会变得昂贵。 – nickb 2013-03-19 17:03:21

+0

我知道它,但出于我自己的原因,我想做一个正则表达式搜索。 这似乎是不可能的,所以我会回到这种方式。 – 2013-03-19 17:03:35