>>> d = "Batman,Superman"
>>> m = re.search("(?<!Bat)\w+",d)
>>> m.group(0)
'Batman'
group(0)がスーパーマンと一致しないのはなぜですか?このルックアラウンドチュートリアルは次のように述べています。
(?<!a)bは、「a」が前に付いていない「b」と一致し、ネガティブルックビハインドを使用します
>>> d = "Batman,Superman"
>>> m = re.search("(?<!Bat)\w+",d)
>>> m.group(0)
'Batman'
group(0)がスーパーマンと一致しないのはなぜですか?このルックアラウンドチュートリアルは次のように述べています。
(?<!a)bは、「a」が前に付いていない「b」と一致し、ネガティブルックビハインドを使用します
Batman
の直前にがないBat
ため、最初に一致します。実際、どちらもそうではありませんSuperman
。文字列の中にコンマがあり、その RE を一致させるのに問題ありませんが、文字列の前の方に一致する可能性があるため、とにかく一致しません。
たぶん、これはよりよく説明します:文字列がBatman
で、 から一致させようとしたm
場合、RE は ( の一致を与えるan
)の後の文字まで一致しませんBat
。
\w+
「Bat」が前に付いていない1 つ以上の英数字 ( ) の最初のセットを探しています。バットマンはそのような最初の試合です。(否定の後読みアサーションは、文字列の先頭に一致する可能性があることに注意してください。)
マニュアルから:
否定の後読みアサーションで始まるパターンは、検索される文字列の先頭で一致する可能性があります。
http://docs.python.org/library/re.html#regular-expression-syntax
単純なレベルでは、正規表現エンジンは文字列の左から開始し、徐々に右に向かって移動して、パターンに一致させようとします (文字列内を移動するカーソルのように考えてください)。ルックアラウンドの場合、カーソルが停止するたびにルックアラウンドがアサートされ、true の場合、エンジンは引き続き一致を試みます。エンジンがパターンに一致するとすぐに、一致が返されます。
文字列の位置 0 (つまりB
inの前) で、現在の位置の前に存在しないためBatman
、アサーションは成功しました。したがって、単語全体に一致する可能性があります (正規表現は本質的に貪欲であることを思い出してください。つまり、可能)。Bat
\w+
Batman
エンジン内部の詳細については、このページを参照してください。
あなたが望むものを達成するために、代わりに次のようなものを使うことができます:
\b(?!Bat)\w+
このパターンでは、エンジンは、単語の境界( \b
) 1とそれに続く 1 つ以上の単語の文字を、単語の文字が で始まらないというアサーションで照合しBat
ます。ここで後読みを使用すると、元のパターンと同じ問題が発生するため、後読みではなく先読みが使用されます。単語境界の直後の位置の前を検索し、カーソルの前の位置が単語境界であることが既に決定されているため、負の後読みは常に成功します。
1\w
単語境界は、 andの間の境界に一致することに注意してください\W
(つまり、[A-Za-z0-9_]
と 他の文字の間。また、^
and$
アンカーにも一致します)。境界をより複雑にする必要がある場合は、別の方法でパターンを固定する必要があります。
やりたいことを行うには、正規表現を'man'
具体的に一致するように制約する必要があります。それ以外の場合は、他の人が指摘したように、\w
を含むすべてのものに貪欲に一致し'Batman'
ます。次のように:
>>> re.search("\w+(?<!Bat)man","Batman,Superman").group(0)
'Superman'