2013-03-19 44 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