2016-04-04 220 views
-1

代碼奇怪的問題:PHP正則表達式 - 多組捕獲

$pattern = '~(/(?P<lang>en|ru))?/foo(/(?P<bar>bar))?~'; 

preg_match($pattern, '/foo', $matches); 
var_dump($matches); 
/*output: 
array(1) { 
    [0] => 
    string(4) "/foo" 
}*/ 
preg_match($pattern, '/foo/bar', $matches); 
var_dump($matches); 
/*output: 
array(7) { 
    [0] => 
    string(8) "/foo/bar" 
    [1] => 
    string(0) "" 
    'lang' => 
    string(0) "" 
    [2] => 
    string(0) "" 
    [3] => 
    string(4) "/bar" 
    'bar' => 
    string(3) "bar" 
    [4] => 
    string(3) "bar" 
}*/ 

的問題:到底爲什麼它捕捉到第二的preg_match呼叫<lang>,如何解決?

P.S.我在https://www.regex101.com上試過這個正則表達式,並且它正確捕獲,但是在我的機器上使用PHP7,它並沒有正確捕獲。我感覺到regex101過濾輸出。

+0

不知道你的意思,但也許懶惰匹配可以幫助:'(/(?P en | ru))??/foo(/(?P bar))?' –

+0

我的意思是它不應該捕獲當沒有匹配的時候'lang'。這沒有任何意義。不,添加另一個'?'沒有幫助。 – jurchiks

+0

請澄清。我在你的代碼演示中看到'lang'爲空:'lang'=> string(0)「」'。沒有文字被捕獲。 –

回答

1

正如其他人所說,這就是正則表達式的工作原理。就我所知,正則表達式相當普遍。它甚至在編程方面也有相似之處,比如Java需要String返回函數返回String(除非它拋出錯誤)。

在PHP中,使用array_filter$matches刪除空條目。

另外,我建議使用非捕獲組(?:)削減雜波:

(?:/(?P<lang>en|ru))?/foo(?:/(?P<bar>bar))?

或者它分成2個正則表達式:(?:/(?P<lang>en|ru))/foo(?:/(?P<bar>bar))