2012-12-31 6 views
9

これは本当に簡単な質問ですが、どこでも答えは見つかりません。改行や文字列の末尾に一致する正しい正規表現の構文が見つかりません

(注:私は、Pythonを使用していますが、これは問題にはならない。)

は、私は次の文字列を持っていると言う:

s = "foo\nbar\nfood\nfoo" 

私は単純にマッチする正規表現を見つけようとしています両方のインスタンス "foo"ではなく、 "food"ではなく、 "food"の "foo"に改行または文字列の終わりの直後にはないという事実に基づいています。

これは多分私の質問を表現するにはあまりにも複雑な方法ですが、それは具体的なものを提供します。結果は(注:私が望む結果は[foo\nfoo]である):でここ

は、私が試してみました事柄のいくつかである

foo[\n\Z] => ['foo\n']

foo(\n\Z) => ['\n'''] < =これは、改行とEOSと一致するようだが、ないfoo

foo($|\n) => ['\n''']

(foo)($|\n) => [(foo'\n')、(foo'')] =ほとんどが<、これは使用可能なプランBですが、私は完璧な解決策を見つけるしたいと思います。

私はそれが仕事をしただけの事はある:

foo$|foo\n => ['foo\n'、 `「FOO」]

これは、このような単純な例の罰金ですが、どのようにそれを見るのは簡単ですはるかに大きな表現で扱いにくくなる可能性があります(そして、これは私が実際に使っているより大きな表現のためのものです)。余談


興味深い:、私は単に私の「特定の文字」の\nを置き換えることができここでIn regex, match either the end of the string or a specific character

:私は私の問題に見つけることができる最も近いSOの質問はこれ一つでした。今、受け入れられた答えは、正規表現/(&|\?)list=.*?(&|$)/を使用しています。私はOPがJavaScriptを使用していたことに気づきました(質問にはjavascriptというタグがついていました)ので、JavaScript正規表現インタープリタが異なるかもしれませんが、Pythonで上記の正規表現を使って質問に与えられた正確な文字列を使用すると、

>>> findall("(&|\?)list=.*?(&|$)", "index.php?test=1&list=UL") 
[('&', '')] 
>>> findall("(&|\?)list=.*?(&|$)", "index.php?list=UL&more=1") 
[('?', '&')] 

だから私は困惑しています。

+0

あなたは[re.MULTILINE](http://docs.python.org/2/library/re.html)について知っていますか? –

+0

はい、私はPythonで私にとってはうまくいくことを知っていますが、私は言語にとらわれないソリューションを探したいと思います。 –

答えて

7
>>> import re 
>>> re.findall(r'foo(?:$|\n)', "foo\nbar\nfood\nfoo") 
['foo\n', 'foo'] 

(?:...)non-capturing groupになります。

これが原因( re module referenceから)作品

re.findall(パターン、文字列、フラグ= 0)

戻り、すべての重複しない文字列のリストとして、文字列のパターンが一致しました。文字列は左から右にスキャンされ、一致するものは見つかった順序で返されます。 パターンに1つ以上のグループがある場合は、グループのリストを返します。パターンに複数のグループがある場合は、これはタプルのリストになります。空のマッチは、別のマッチの先頭に触れない限り、結果に含まれます。

+0

Huh。標準グループの代わりに非キャプチャグループを使用するのはなぜですか?なぜ普通の 'r'foo($ | \ n) ''も同じことをしないのですか? –

+0

また、これは私が欲しかったものです。どうもありがとう! –

+1

普通のグループに '$ | \ n'がある場合は、(キャプチャグループ内に何もないので)改行をマッチさせるだけです。グループ内にfooを置くこともできますが、改行のためにグループ結果を追加することになります。 – poke

1

あなただけfooに関係している場合:

In [42]: import re 

In [43]: strs="foo\nbar\nfood\nfoo" 

In [44]: re.findall(r'\bfoo\b',strs) 
Out[44]: ['foo', 'foo'] 

\bさは、ワード境界を表し:

\b

はなく、唯一の最初か最後に、空の文字列にマッチします単語の。単語は、英数字またはアンダースコアのシーケンスとして定義されます。単語の末尾は、空白または英数字以外の非アンダースコアの 文字で示されます。 文字。正式には、\ bは\ wと\ W文字の境界(またはその逆)として定義された であることに注意してください。 の文字セットは\ wと文字列の先頭と末尾の間にあります。英数字であるかどうかは、UNICODEおよびLOCALEフラグの値の に依存します。例えば、r '\ bfoo \ b' は 'foo'、 'foo'、 '(foo)'、 'bar foo baz'に一致しますが、 'foobar'や 'foo3'には一致しません。文字の範囲内では、\ bはバックスペース 文字を表し、Pythonの文字列リテラルとの互換性を保ちます。

Source

+0

['\ b'](http://docs.python.org/2/library/re.html#regular-expression-syntax)について説明する価値があります。 –

+0

また、 'foo'ははるかに複雑な表現の単なるプレースホルダーです。私が本当に探しているのは、行末や文字列の終わりをチェックする方法です。多くの場合、 '\ b'を使って単語の境界をチェックすると、式が壊れる可能性があります。しかし考えました。 –

+2

@KenBあなたが望むものを実際に示す例を挙げてください。あなたがそれらを表示しないと、あなたの要件を推測するのは難しいです。 –

2

あなたは後、あなたのパターンで$re.MULTILINEを使用して、オプションの改行を含めることができます

s = "foo\nbar\nfood\nfoo" 
pattern = re.compile('foo$\n?', re.MULTILINE) 
print re.findall(pattern, s) 
# -> ['foo\n', 'foo'] 
+0

私はそれが好きですが、言語にとらわれないソリューションを見つけることを本当に好むでしょう。 're.MULTILINE'はPython特有のものなので、将来は他の言語で使うために避けています。 –

+3

ほとんどの正規表現エンジンは複数行オプションをサポートしています。 're.findall( '(?m)foo $ \ n?'、s)'パターンに直接埋め込むこともできます。 – omz

+1

@KenBまさにMULTILINEのようなフラグはPython固有ではなく、他の言語では構文が異なります(例えば、Perl 're.MULTILINE'は' $ s =〜/ blah/m'などとなります)。私はフラグがパターンに含まれていることを理解したことはありませんでした。本当に知っておくと便利です。ありがとう! :D – dbr

関連する問題