2011-09-07 13 views
6

私は周りを見てきましたが、これを行うことができませんでした。私は全く騒ぎではない。Regex - 単語を含まない2つの単語の間の文字列を取得

STARTを含まないSTARTとENDで区切られたテキストを取得する必要があります。基本的には、高度なものを使わずに単語全体を否定する方法は見つけられません。

例文字列:

abcSTARTabcSTARTabcENDabc

期待される結果:

良くない

STARTabcEND:

STARTabcSTARTabcEND

私は後方検索のものを使用することはできません。私はここに私の正規表現をテストしてい:どんなアドバイスをwww.regextester.com

感謝を。

+0

テキストが 'abcSTARTabcENDabcSTARTabcENDabc'の場合はどうなりますか?両方の試合が欲しいですか? –

+0

それについては考えていませんでした...とにかく、必要に応じて2番目の試合を見つけることができます。 – rrr

+0

これを単一の正規表現で行う方がよいでしょう。私は答えを加えました。 –

答えて

4

本当に歩行者ソリューションはSTART(([^S]|S*S[^ST]|ST[^A]|STA[^R]|STAR[^T])*(S(T(AR?)?)?)?)ENDだろう。現代の正規表現のフレーバはこれをよりエレガントにする否定的なアサーションを持っていますが、この機能を使用できない、またはしたくないことを意味する "後方検索"に関するあなたのコメントを解釈します。

更新:完全性のために、上記は終了区切り記号に対して貪欲であることに注意してください。可能な最短の文字列だけをキャプチャするには、否定を拡張して末尾の区切り文字 - START(([^ES]|E*E[^ENS]|EN[^DS]|S*S[^STE]|ST[^AE]|STA[^RE]|STAR[^TE])*(S(T(AR?)?)?|EN?)?)ENDもカバーします。しかし、このことは、ほとんどの文化において拷問閾値を超える危険性がある。

バグ修正:この回答の以前のバージョンでは、そのSSTARTのバグは、試合の一部(第2 S[^T]、などと一致します)することができました。私はこれを修正しましたが、S[^ST]に追加し、S*を追加する前に、任意のSの前にSの任意の繰り返しを許可してください。

+0

良い解決策(先読みができない場合)+1 – stema

+0

+1先読みなしでの表示方法 – shelleybutterfly

+0

これは私が探していたものです。ありがとうございます。確かに...歩行者:)しかし、それは動作します。私は、私が行方不明になっているより簡単な方法があると思っていました。以前にポストバックしていないことを申し訳ありません。 – rrr

10

here online on Regexr

(?!.*START)は否定先読みで、それを参照してください。この

START(?!.*START).*?END 

を試してみてください。これは、単語「START」が次の「END」までのすべての文字を非欲張りマッチが

.*?をされて、次のされていないことを保証します。その負の先読みだけの先読みと何も(長さゼロのアサーション)を捕捉していないので、必要に応じ

更新:

私は、上記の溶液は、最初に「END」までマッチングされ、もう少し考えました。 (あなたがコンテンツからSTARTを除くため)これが欲しかっされていない場合は、

貪欲なバージョンを使用
START(?!.*START).*END 

これが最後の「END」まで一致します。

+0

+1 19秒で私を倒してください。 :) –

+0

+1うまくやった。 –

+0

+ 1すべての演算子の簡単な説明で良い答えのため – shelleybutterfly

0

[編集:私はキャプチャグループに関する情報についてこの投稿を残しましたが、私が与えた主な解決策は正しくありませんでした。 (?:START)((?:[^S]|S[^T]|ST[^A]|STA[^R]|STAR[^T])*)(?:END) コメントで指摘されているように機能しませんでした。私は、無視された文字が削除されないことを忘れていたので、あなたは... |STA(?![^R])|のようなものが必要になりますが、その文字はENDの一部であるため、STARTSTAENDなどでは失敗します。それは明らかに良い選択です。キャプチャグループを使用する適切な方法を以下に示す必要があります...]

キャプチャグループを持つ「ゼロ幅ネガティブ先読み」演算子「?!」を使用して得られた答えは、(?:START)((?!.*START).*)(?:END)です。内部テキストをキャプチャします置き換えに$ 1を使用します。 STARTタグとENDタグを取得したい場合は、(START)((?!.*START).*)(END)を実行して、$ 1 = START $ 2 = textと$ 3 = END、またはまたは?:を追加/削除することで、さまざまな順列を与えることができます。

このようにして検索や置換を行う場合は、BEGIN $ 1FINISHのようにすることができます。だから、あなたが開始した場合:

abcSTARTdefBEGINghiFINISHjklあなたを許す

abcSTARTdefSTARTghiENDjkl

あなたはキャプチャグループ1としてghiになるだろう、として交換はあなたに次を与えるだろう$ 1FINISHをBEGIN START/ENDトークンを正しくペアにした場合にのみ変更できます。

(x)はグループですが、私は(?:x)を非捕捉グループとしてマークする中間を除いてそれぞれに入れました。私が?:なしで去った唯一の人は中央でした。しかし、BEGIN/ENDトークンをキャプチャすることも考えられます。

Java正規表現の詳細については、Java regex documentationを参照してください。

+0

パターンSTARTSTAENDに失敗しました。 – tripleee

+0

@ tripleee sigh、はい、確かに私はそれらの文字を無視する必要がありますか?それはまったく目的を破るものです。それを指摘してくれてありがとう。 – shelleybutterfly

4
START(?:(?!START).)*END 

は任意の数のSTART...ENDペアで動作します。あなただけSTARTEND間でのコンテンツの世話をした場合、

>>> import re 
>>> a = "abcSTARTdefENDghiSTARTjlkENDopqSTARTrstSTARTuvwENDxyz" 
>>> re.findall(r"START(?:(?!START).)*END", a) 
['STARTdefEND', 'STARTjlkEND', 'STARTuvwEND'] 

これを使用します:Pythonで証明するために、

(?<=START)(?:(?!START).)*(?=END) 

は、ここでそれを参照してください。

>>> re.findall(r"(?<=START)(?:(?!START).)*(?=END)", a) 
['def', 'jlk', 'uvw'] 
+0

うん、これはそれを行います。 +1( 's'のdot-matches-allフラグについて言及/使用したいかもしれませんが) – ridgerunner

2

が、私は可能性を示唆するかもしれませんTim Pietzckerのソリューションの改善? STARTをただちにキャッチするためにはSTART(?:(?!START).)*?ENDが良いと思われますが、その間にSTARTまたはENDのないENDが続きます。私は.NETを使用しており、TimのソリューションはSTART END ENDのようなものにも一致します。少なくとも個人的にはこれは望ましくない。

関連する問題