findall()
(1)の代わりに使用search()
し、(2)非キャプチャの代わりにキャプチャグループを使用しているため、追加の結果が得られます。
>>> import re
>>> re.search(r'^(?:(?:(?!exclude).)*(?=test)*)$', "/this/test").group(0)
'/this/test'
これも機能しfindall()
ますが、文字列全体を一致させる場合は、実際には意味がありません。さらに重要なのは、正規表現のインクルード部分が機能しないことです。これをチェックして:
>>> re.search(r'^(?:(?:(?!exclude).)*(?=test)*)$', "/this/foo").group(0)
'/this/foo'
これは、*
in(?=test)*
によって先読みがオプションになり、意味がなくなるためです。しかし、を取り除くこと*
は実際には解決策ではありません。なぜならexclude
、test
はやのような長い単語の一部である可能性があるからexcludexx
ですyyytest
。これがより良い正規表現です:
r'^(?=.*/test\b)(?!.*/exclude\b)(?:/\w+)+$'
テスト済み:
>>> re.search(r'^(?=.*/test\b)(?!.*/exclude\b)(?:/\w+)+$', '/this/test').group()
'/this/test'
>>> re.search(r'^(?=.*/test\b)(?!.*/exclude\b)(?:/\w+)+$', '/this/foo').group()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'
編集:「オプションの先読み」の問題を修正したようですが、正規表現全体がオプションになりました。
編集:後で一致を停止したい場合は/test
、これを試してください:
r'^(?:/(?!test\b|exclude\b)\w+)*/test\b'
(?:/(?!test\b|exclude\b)\w+)*
/test
またはでない限り、0個以上のパスコンポーネントに一致します/exclude
。