概念的には正規表現はDFAとしてモデル化されているため、正規表現は各部分文字列を個別にチェックするよりも優れていると思います。したがって、入力が消費されると、すべての一致が同時にテストされます (入力文字列の 1 回のスキャンが発生します)。 )。
例を次に示します。
import re
def work():
to_find = re.compile("cat|fish|dog")
search_str = "blah fish cat dog haha"
match_obj = to_find.search(search_str)
the_index = match_obj.start() # produces 5, the index of fish
which_word_matched = match_obj.group() # "fish"
# Note, if no match, match_obj is None
更新:
単語を組み合わせて代替単語の単一パターンにする場合は、注意が必要です。次のコードは正規表現を作成しますが、正規表現の特殊文字をすべてエスケープし、単語を並べ替えて、長い単語が同じ単語の短い接頭辞より前に一致する機会を得るようにします。
def wordlist_to_regex(words):
escaped = map(re.escape, words)
combined = '|'.join(sorted(escaped, key=len, reverse=True))
return re.compile(combined)
>>> r.search('smash atomic particles').span()
(6, 10)
>>> r.search('visit usenet:comp.lang.python today').span()
(13, 29)
>>> r.search('a north\south division').span()
(2, 13)
>>> r.search('012cat').span()
(3, 6)
>>> r.search('0123dog789cat').span()
(4, 7)
更新を終了
正規表現 (つまり、re.compile() の呼び出し) をできるだけ少なくしたいことに注意してください。最良のケースは、検索が何であるかを事前に知っており (または、検索を 1 回またはまれに計算し)、re.compile の結果をどこかに保存することです。私の例は単なる意味のない関数なので、正規表現の使用法を確認できます。ここにいくつかの正規表現ドキュメントがあります:
http://docs.python.org/library/re.html
お役に立てれば。
更新: Python が正規表現をどのように実装しているかはわかりませんが、re.compile() の制限があるかどうかについての Rax の質問に答えるために (たとえば、一度に一致させるために "|" を一緒に試行できる単語の数) 、およびコンパイルの実行時間: どちらも問題ではないようです。私はこのコードを試してみましたが、これは私を納得させるのに十分です. (タイミングを追加して結果を報告し、単語のリストをセットに入れて重複がないようにすることで、これを改善できたかもしれませんが、これらの改善はどちらもやり過ぎのようです)。このコードは基本的に瞬時に実行され、(サイズが 10 の) 2000 語を検索できること、およびそれらが適切に一致することを確信しました。コードは次のとおりです。
import random
import re
import string
import sys
def main(args):
words = []
letters_and_digits = "%s%s" % (string.letters, string.digits)
for i in range(2000):
chars = []
for j in range(10):
chars.append(random.choice(letters_and_digits))
words.append(("%s"*10) % tuple(chars))
search_for = re.compile("|".join(words))
first, middle, last = words[0], words[len(words) / 2], words[-1]
search_string = "%s, %s, %s" % (last, middle, first)
match_obj = search_for.search(search_string)
if match_obj is None:
print "Ahhhg"
return
index = match_obj.start()
which = match_obj.group()
if index != 0:
print "ahhhg"
return
if words[-1] != which:
print "ahhg"
return
print "success!!! Generated 2000 random words, compiled re, and was able to perform matches."
if __name__ == "__main__":
main(sys.argv)
更新:正規表現で論理和をとったものの順序が重要であることに注意してください。TZOTZIOYに触発された次のテストを見て。
>>> search_str = "01catdog"
>>> test1 = re.compile("cat|catdog")
>>> match1 = test1.search(search_str)
>>> match1.group()
'cat'
>>> match1.start()
2
>>> test2 = re.compile("catdog|cat") # reverse order
>>> match2 = test2.search(search_str)
>>> match2.group()
'catdog'
>>> match2.start()
2
これは、順序が重要であることを示唆しています:-/。これが Rax のアプリケーションにとって何を意味するのかはわかりませんが、少なくとも動作はわかっています。
更新: Python での正規表現の実装に関するこの質問を投稿しました。これにより、この質問で見つかった問題についての洞察が得られることを願っています。