2012-11-30 2 views
7

テキストの近くに別のテキストブロックがない場合、一部のテキストをマッチングしようとしています。たとえば、"foo"が先行しない場合は、"bar"と一致させたいと思います。 "foo"はすぐは、この正規表現で後ろの負の外観を使用して、それに先行していないない場合、私は"bar"を一致させることができます:ワイルドカードを使用した正規表現のネガティブなヒアビヘイド

/(?<!foo)bar/ 

私も"foo 12345 bar"と一致していないのが好き。私は試しました:

/(?<!foo.{1,10})bar/ 

ワイルドカード+を使用すると、範囲がRubyで無効な正規表現に見えます。私は間違った問題について考えていますか?

答えて

9

あなたは正しい方法を考えています。しかし、残念なことにlookbehindsは通常固定長である。唯一の主な例外は、.NETの正規表現エンジンです。この正規表現エンジンは、lookbehindの内側に繰り返し数量子を使用できます。しかし、あなたはネガティブなルックバックを必要とし、先読みを必要としないので、あなたのためのハックがあります。

/rab(?!.{0,10}oof)/ 

その後、それはあなたが後にしているものだならば、試合の結果を反転させるか、文字列の長さからマッチング位置を減算:一致させよう、その後、文字列を逆にします。

あなたが与えた正規表現から、これは実際に必要なものの単純化されたバージョンだと思います。もちろん、barが複雑なパターンそのものであれば、それを正しく逆転させる方法を考える必要があります。

あなたのパターンが可変長ルックビハインドと先読みの両方を必要とする場合は、これを解決するのにもっと時間がかかることに注意してください。

/(?<!foo)(?<!foo.)(?<!foo.{2})(?<!foo.{3})(?<!foo.{4})(?<!foo.{5})(?<!foo.{6})(?<!foo.{7})(?<!foo.{8})(?<!foo.{9})(?<!foo.{10})bar/ 

しかし、それはそれは、その素敵すべてではありません。(あなたはどちら+*を使用しているため)また、あなたのケースでは、複数の可変長のものにあなたの後読みを分解することは可能でしょうか?

+1

は面白いアイデアでした。ありがとう! –

3

m.buettnerには既に言及しているように、Ruby正規表現のlookbehindは固定長でなければならず、そのドキュメントでも説明されています。したがって、あなたは見た目の中に量子を置くことはできません。

すべてを一度に確認する必要はありません。あなたが望むものを得るために、正規表現マッチの複数のステップを実行してみてください。その後、関係なく、別のbarがあるかどうかの

string.match(/bar/) and !string.match(/foo.*bar/) 

barブレイク条件の単一のインスタンスの前でfooの存在を仮定すると、あなたが例えば何をしたいあなたを与えるだろう。文字列を逆にあなたはむしろ試合はbar foo barで成功したい場合は、あなたが行うことができます。この

string.scan(/foo|bar/).first == "bar" 
+0

実際にマッチを検索するというのは、問題である。 'bar foo bar'を持っているとします。 OPが試した正規表現は、最初の 'bar'を検索します。あなたの解決策はマッチがないと主張するでしょう。 (あなたが "10文字までの"ヒューリスティックを省略したという事実は別として) –

+0

@ m.buettnerあなたと私は質問とは異なる解釈をしています。 – sawa

+1

確かに。私はあなたの解決策が間違っているとは言いません。しかし、私はそのような前提と違いが述べられていることが重要であることを知ります。彼らは将来、この質問を見つけるOPや他の誰にも明らかではないかもしれないからです。 –

関連する問題