2009-03-04 32 views
2

我目前在一個的preg_match使用3個不同的正則表達式的結果進行排序,使用或登錄|將它們分開。這工作完美。然而,第一個和第二個正則表達式具有相同類型的輸出。例如[0]源文本[1]數量金額[2]名稱 - 但是最後一個,因爲它使用不同的源文本排列結果:[0]源文本[1]名稱[2]數量。棘手的問題:如何從多個正則表達式

preg_match('/^Guo (\d+) Cars @(\w+)|^AV (\d+) Cars @(\w+)|^@(\w+) (\d+) [#]?av/i', $source, $output); 

由於Name能夠是數字我不能做一個簡單的檢查,看它是否是數字。有沒有辦法可以切換正則表達式中的順序,或者找出它匹配的正則表達式。速度是這裏的關鍵,所以我不想使用3個單獨的preg_match語句(以及更多)。

回答

3

三個獨立的正則表達式沒有要慢一些。一個大的聲明將意味着對正則表達式引擎的很多回溯。正則表達式優化的關鍵在於使引擎儘快失效。你有沒有做一些基準測試來拉動它們?

在您的情況下,您可以使用PCRE的命名捕獲(?<name>match something here)並替換爲${name}而不是\1。我不是100%確定這適用於preg_replace。不過,我知道preg_match正確地存儲了某些命名的捕獲。

PCRE需要與PCRE_DUPNAMES選項編譯爲在你的情況下非常有用(如RoBorg的)職位。我不確定PHP編譯的PCRE DLL文件是否具有該選項。

+0

的Martijn嗨, 謝謝你的回答,你是正確的PCRE不與這裏的DUPNAMES選項編譯意味着我不能使用相同的組名稱。 我不知道單獨的REGEX可能會更快。我還沒有做過任何基準測試。 – Ice 2009-03-04 14:54:31

3

你可以使用一個名爲捕獲組:

preg_match('/^Guo (?P<number_amount>\d+) Cars @(?P<name>\w+)|^AV (?P<number_amount>\d+) Cars @(?P<name>\w+)|^@(?P<name>\w+) (?P<number_amount>\d+) [#]?av/i', $source, $output); 
0

我不知道因爲什麼版本PCRE支持duplicate subpattern numbers syntax (?| …)。不過,試試這個正則表達式:

/^(?|Guo (\d+) Cars @(\w+)|AV (\d+) Cars @(\w+)|@(\w+) (\d+) #?av)/i 

所以:

$source = '@abc 123 av'; 
preg_match('/^(?|Guo (\\d+) Cars @(\\w+)|AV (\\d+) Cars @(\\w+)|@(\\w+) (\\d+) #?av)/i', $source, $output); 
var_dump($output);