2016-11-11 27 views
0

我試圖創建一個用於分割字符串的正則表達式,但不幸的是我的需求比簡單的分割複雜一點,所以我不能在PHP中使用例如preg_split()Extraneous Empty Trailing Match

所以我在做什麼是匹配我的分隔符(或者說,它們的一部分)在一個子表達式中,以及它在另一個子表達式中的一切,並且還將字符串的末尾作爲分隔符來處理目的。考慮到這一點,我想出了以下內容:

([^?;]*)(?|\?([0-9]*)|(;)|$) 

正如你可以看到希望,第一子圖案查找文本塊沒有分號的任何問號。在此之後,我有一個子模式匹配任何問號和後面的可選數字(存儲),可以是分號(存儲)或字符串結尾。

的問題是,我似乎越來越反對串案件結束外來,空,比賽,像這樣:

$sql = 'CALL foo(?0, ?1, ?2, ?3)'; 
preg_match_all('/([^?;]*)(?|\?([0-9]*)|(;)|$)/', $sql, $matches); 
print_r($matches); 

產生輸出看起來像:

Array 
(
    [0] => Array 
     (
      [0] => CALL insert_host(?0 
      [1] => , ?1 
      [2] => , ?2 
      [3] => , ?3 
      [4] =>) 
      [5] => 
     ) 

    [1] => Array 
     (
      [0] => CALL insert_host(
      [1] => , 
      [2] => , 
      [3] => , 
      [4] =>) 
      [5] => 
     ) 

    [2] => Array 
     (
      [0] => 0 
      [1] => 1 
      [2] => 2 
      [3] => 3 
      [4] => 
      [5] => 
     ) 

) 

$matches[0][5]下的空比賽;我希望在匹配括號後能夠滿足字符串大小寫的結尾,導致沒有進一步的匹配,但它繼續產生另一個匹配,我不知道爲什麼。

所以我的問題是,爲什麼會在這裏製作額外的比賽,我該如何防止呢?

注意:我已經考慮要求字符串大小寫的結尾至少有一個字符在它之前,但這是不好的,因爲我實際上想要一個空的結果,如果通配符是在字符串,因爲我試圖模擬分裂函數的行爲。例如,如果輸入是SELECT ?,我希望匹配SELECT ?加上一個空字符串。這裏的想法是,一旦我處理了任何匹配的分號,我就可以簡單地使用implode('?', $matches[1])來重新生成帶有數字通配符的語句。

回答

0

我相信我可能已經想出了一個替代我的具體案例,可以解決問題;我做了什麼翻轉表達周圍使得定界符匹配的第一或者,做不到這一點,字符串的開始,像這樣:

(?|\?([0-9]*)|(;)|^)([^?;]*) 

這將產生預期的結果在所有情況下:

preg_match_all('/(?|\?([0-9]*)|(;)|^)([^?;]*)/', 'CALL foo(?3, ?2, ?1, ?0)', $matches); 
print_r($matches); 

產地:

Array 
(
    [0] => Array 
     (
      [0] => CALL foo(
      [1] => ?3, 
      [2] => ?2, 
      [3] => ?1, 
      [4] => ?0) 
     ) 
    [1] => Array 
     (
      [0] => 
      [1] => 3 
      [2] => 2 
      [3] => 1 
      [4] => 0 
     ) 

    [2] => Array 
     (
      [0] => CALL foo(
      [1] => , 
      [2] => , 
      [3] => , 
      [4] =>) 
     ) 
) 

雖然:

preg_match_all('/(?|\?([0-9]*)|(;)|^)([^?;]*)/', 'SELECT ?', $matches); 
print_r($matches); 

產地:

Array 
(
    [0] => Array 
     (
      [0] => SELECT 
      [1] => ? 
     ) 
    [1] => Array 
     (
      [0] => 
      [1] => 
     ) 
    [2] => Array 
     (
      [0] => SELECT 
      [1] => 
     ) 
) 

然而,這隻能是因爲我知道,輸入絕不會包括一個分隔符作爲第一個字符;如果我提供一個它遇到很多相同的問題,所以我不確定是否稱它爲真正的解決方案。

我還有興趣知道爲什麼我的原始表達式獲得了額外的匹配,因爲我預料貪婪匹配意味着它是不可能的,因爲一旦匹配字符串的末尾,應該沒有任何東西留給找。