2010-12-08 5 views
4

置き換えられる/取り除かれる正規表現(PHP)は何ですか(preg_replace()を使用します)。ここで置換されていない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

パーサーが必要な場合は、パーサーを作成する必要があります。 –

+0

ネストされた区切り文字のレベル(括弧、括弧、開始/終了など)を認識しなければならない場合は、解析ライブラリを使用するか、通常のプッシュダウンオートマトンを使用することを検討してください表現。あなたのプラットフォームの正規表現ライブラリがこれを可能にする拡張をサポートしていても、その解決法は壊れやすく、維持するのが難しいでしょう。 –

+0

私は余分なENDを修正する小さな正規表現のパーサを探しているわけではありません。私の正規表現のスキルは限られていますが、私はそれを取り替えるためにSTARTによって進められなかったかどうかをどうやって確認するのか分かりません。 – Newbtophp

答えて

8

ネストされたペアを探していないと仮定すると、余分なENDをリコールする簡単な解決策があります。以下を考慮してください:

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

これは少し後方に置き換えられていますが、エンジンの動作順序を理解すれば意味があります。まず、正規表現は2つの主要部分、すなわちEND|()で作られています。交互の操作は左から右へ試行されるので、エンジンが入力文字列内にENDを見つけた場合、それは一致して次の一致に移動します(つまり、ENDを再度探します)。
2番目の部分はキャプチャグループで、START.*?ENDが含まれています。可能であれば、Start/Endトークン全体と一致します。別のENDまたはSTARTが見つかるまで、他のすべてはスキップされます。

置換されたグループであるreplaceに$1を使用しているので、2番目のトークンのみを保存します。そのため、ENDが生き残る唯一の方法は、STARTの後の最初のキャプチャグループに入ることです。

たとえば、テキストEND START 123 END abc ENDの場合。正規表現は、次の一致を検索し、維持、スキップしたり、それに応じてそれらを削除します:

  • ENDから
  • (START 123 END)を削除 -
  • aをキャプチャ - スキップ
  • b - スキップ
  • c - スキップ
  • END - 削除済み

実例:http://ideone.com/suVYh

+0

キャプチャグループを使った素晴らしい答え。大好きです。 :) – zx81

2

これは非正規語のテキストブックの例です(STARTとENDは括弧の開閉に相当します)。つまり、この言語を単純な正規表現と照合することはできません。あなたは複雑な正規表現を使って特定の深さにすることができますが、任意の深さにすることはできません。

言語パーサーを作成する必要があります。

関連資料:

http://www.amazon.com/Introduction-Automata-Theory-Languages-Computation/dp/0321462254/ref=sr_1_1?ie=UTF8&qid=1291768284&sr=8-1

0

すべての可能な構文については、正規表現を記述することはできません。あなたのケースでは、上層または下層のようなコンテキストフリーのパーサーが必要な場合があります。参照:http://en.wikipedia.org/wiki/Formal_grammar

関連する問題