2010-12-08 18 views
4

什麼是一個正則表達式(PHP)替換/刪除(使用preg_replace())結束在哪裏它未被一個未完成的START?什麼是替換/刪除END的正則表達式,前面沒有未完成的START?

這裏有幾個例子來描繪我的意思更好:

例1:

輸入:

sometext....END 

輸出:

sometext.... //because theres no START, therefore no need for the excess END 

實施例2:

輸入:

STARTsometext....END 

輸出:

STARTsometext....END //because its preceded by a START 

實施例3:

輸入:

STARTsometext....END.......END 

輸出:

STARTsometext....END....... //because the END is not preceded by a START 

希望有人能幫忙嗎?

謝謝。

+1

如果你想要一個解析器,你需要編寫一個解析器。 – 2010-12-08 00:24:17

+0

一旦你需要識別嵌套分隔符(parens,括號,開始/結束等)的級別,你應該考慮使用解析庫,甚至是自己的簡單下推自動機,而不是常規表達。即使您的平臺的正則表達式庫支持使其成爲可能的擴展,解決方案可能會很脆弱並且難以維護。 – 2010-12-08 00:32:58

回答

8

假設您沒有在尋找嵌套對,有一個簡單的解決方案來刪除多餘的END。考慮:

$str = preg_replace("/END|(START.*?END)/", "$1", $str); 

這是一個小倒退替換,但它是有道理的,如果你瞭解引擎的工作順序。首先,正則表達式由兩個主要部分組成:END|()。從左到右嘗試更改,因此如果引擎在輸入字符串中看到END,它將匹配它並繼續進行下一個匹配(即再次查找END)。
第二部分是一個捕獲組,其中包含START.*?END - 如果可能,這將匹配整個開始/結束標記。一切都會被跳過,直到找到另一個END或START。

由於我們在替換中使用了$1,這是捕獲的組,我們只保存第二個標記。因此,END生存的唯一方法就是進入捕獲組,成爲START之後的第一個。

例如,對於文本END START 123 END abc END。正則表達式會發現下面的比賽,並保持,跳過或相應地刪除它們:

  • END - 刪除
  • (START 123 END) - 捕捉
  • a - 跳過
  • b - 跳過
  • c - 跳過
  • END - 刪除

工作示例:http://ideone.com/suVYh