2016-05-10 11 views
1

私は、対応する 'foo'の文字列を 'bar = 1'、 'bar = 2'または 'bar = 3'のいずれかにマッチさせようとしています。一度に1つしか一致しません。複数行とドットで非貪欲な振る舞い

file_header 

foo lorem ipsum \pope 
24 dolor sit amet, consectetur adipisici elit 
Excepteur sint obcaecat cupiditat non 
gnu blu bar=1 

foo lorem ipsum \ 
@>@[email protected] consectetur adipisici elit 
gnu blu bar=2 
foo lorem ipsum 
23 dolor sit amet, consectetur adipisici elit 
gnu blu bar=3 

foo ... etc 

私は、単純な^foo.*?bar=2$から^(?!\bfoo\b.*\bfoo\b).*\bfoo\b.*bar=2$のようなものに、すべてのものを試してみました。しかし、マルチラインとドットリングを有効にすると、常に最初の 'foo'にマッチするか、ファイルヘッダ全体に印を付けることさえあります。非貪欲な行動ができないように複数行とDOTALLを使用しながら:(

それは、そうです。

+1

だから、['^ foo(?:^ foo | bar = 2 $)。)* bar = 2 $'](https://regex101.com/r/) xM4sX9/1)? –

+0

1)**一致**または**検索**を試みていますか? 2)あなたのエラーを示す短い、完全なプログラムを提供してください。 「私はすべてを試しました」とあなたが考えるほど有用ではないと言っています。代わりに、** complete **プログラムで、あなたが試した特定のものを見せてください。優れた回答を得るための質問の詳細については、[mcve]を参照してください。 –

+0

@Robᵩ私はhttp://pythex.org/で実験していましたが、まだPythonコードはありません。だから、私は一致と検索の違いがあることに気付かなかったのです。 (私は検索が必要です) – CptSausage

答えて

1

あなたは(?:(?!^foo|bar=2$).)*試合に

^foo(?:(?!^foo|bar=2$).)*bar=2$ 

のようなものである任意のテキストを鍛え貪欲なトークンを使用することができますないfooが行/文字列の末尾ではなくbar=2(行/列の先頭に)。

regex demoを参照してください。ただし、このような構築物はリソースを消費している、それがすることをお勧めしますそれを展開します。以下はオプションです:

^foo[^\nb]*(?:\n(?!foo)[^\nb]*|b(?!ar$)[^\nb]*)*bar=2$ 

another demoを参照してください。

+0

ウィクスター、あなたは獣です!ありがとう! – CptSausage

+0

ようこそ。レイジーは常に最短の試合を返すわけではありません。 –

1

このプログラムでは、オーバーラップしないすべての発生をfoo <stuff> bar=<number>としています。この式を使用してre.MULTILINE -modeで非貪欲オペレータの使用の成功に注意してください。^foo.*?bar=\d+$

import re 
from pprint import pprint 

data = ''' 
file_header 

foo lorem ipsum \pope 
24 dolor sit amet, consectetur adipisici elit 
Excepteur sint obcaecat cupiditat non 
gnu blu bar=1 

foo lorem ipsum \ 
@>@[email protected] consectetur adipisici elit 
gnu blu bar=2 
foo lorem ipsum 
23 dolor sit amet, consectetur adipisici elit 
gnu blu bar=3 
''' 

matches = re.findall(r'^foo.*?bar=\d+$', data, re.DOTALL|re.MULTILINE) 
pprint (matches) 

結果:

['foo lorem ipsum \\pope\n24 dolor sit amet, consectetur adipisici elit\nExcepteur sint obcaecat cupiditat non \ngnu blu bar=1', 
'foo lorem ipsum @>@[email protected] consectetur adipisici elit\ngnu blu bar=2', 
'foo lorem ipsum\n23 dolor sit amet, consectetur adipisici elit\ngnu blu bar=3'] 
+1

これは、データがうまく整理され、fooとbarが一致しているためです。入れ子にされたfoo/barがある場合、またはbarが特定のセット(たとえ[234])であっても、内側のfooをbarにすることはできません。 – sln

+0

're.findall(...)'は "重複しないすべてのマッチを返す"ので、これはうまくいくように見えます。 're.search(r '^ foo。*?bar = 3 + $'、...'と 'printed matches.group(0)'と同じコードは最初のfooから最後のbarまでの文字列を返します。それは私が必要とするものではありません。私は英語がベストではないので、次回に必要なもののより良い例を提供します。 :D – CptSausage

1

貪欲それは何の関係もありません左から右

に動作しますMULTILINEまたはDOTALLとすると、それは非欲張りのオペレータ が開始ではなく、試合の最後にのみ影響します。

あなたの欲求を満たすには、パターンの前に.*を追加します。

>>> re.findall(r'.*(foo.*?bar=1)', s, re.DOTALL) 
['foo lorem ipsum \\pope\n24 dolor sit amet, consectetur adipisici elit\nExcepteur sint obcaecat cupiditat non \ngnu blu bar=1'] 
>>> re.findall(r'.*(foo.*?bar=2)', s, re.DOTALL) 
['foo lorem ipsum @>@[email protected] consectetur adipisici elit\ngnu blu bar=2'] 
>>> re.findall(r'.*(foo.*?bar=3)', s, re.DOTALL) 
['foo lorem ipsum\n23 dolor sit amet, consectetur adipisici elit\ngnu blu bar=3']