【 Python + Regular Expressions 】複数のマッチパターンを look ahead (先読み) シンタックスを利用して 1 つのマッチパターンにまとめて処理しよう! re.match() の呼び出しも 1 回で済んじゃいます! 投稿一覧へ戻る

Tags: Python , regular expressions , lookahead

Published 2020年9月11日20:20 by T.Tsuyoshi

時には、テキストが複数の条件に合致しているか、を調べる必要に迫られることもあります。


ユーザーが設定しようとしているパスワードが十分に「安全」かを確認したいような場合もそうですね。


ここでは「十分に安全」なパスワード ( strong passowrd ) の条件を以下のように定めるとします。。


1: 8 文字以上で、アルファベット、数字、句読文字 ( punctuation character ) のいずれもが使用されていること。


2: 少なくとも 1 文字以上のアルファベットの大文字を含むこと


3: 少なくとも 1 文字以上のアルファベットの小文字を含むこと


4: 少なくとも 1 文字以上の数字を含むこと


5: 少なくとも 1 文字以上の句読文字を含むこと




さて、もっとも着実な確認方法は、それぞれの条件に当てはまるパターンを用意し、条件の数だけ re.match() を呼び出して別々にマッチを確認、最終的に全てパターンがマッチすれば strong password であると判断する、というものでしょう。


しかし、look-ahead シンタックスを利用することで、より効率的に複数のパターンマッチを確認することができちゃいます!


re.match() の呼び出しも 1 回で済んじゃいますよ。


さて、その方法ですが、まずは各条件を満たすパターンを用意します。この場合は 5 パターンですね。


pat1 = r'(\w|[!@#$%^&*+-]){8,}$'

pat2 = r'(?=.*[A-Z])'

pat3 = r'(?=.*[a-z])'

pat4 = r'(?=.*\d)'

pat5 = r'(?=.*[!@#$%^&*+-])'



最初のパターンを除く他の全てのパターンでは look ahead シンタックスを採用しています。


これらのパターンを繋げて「長い」1 つのパターンを作成しましょう。


唯一 look ahead シンタックスを利用していない 1 つ目のパターンは最後に連結しますョ!


pat_all = pat2 + pat3 + pat4 + pat5 + pat1



さて、ここでもう一度、look-ahead シンタックスの特徴を思い出してください。


lookahead シンタックスにマッチしたサブ文字列は「消費」されない、のでした。


つまり 「先読み」されたパターン部分は、続くマッチ検索において再び「検索文字列の一部」として検索対象になる、んですね。


よって、文字列の先頭から 1 文字ずつ全てのパターンのマッチが調べられながら進んでいくことになります。


そして、pat1 から pat5 すべてのパターンがマッチした段階で、これらのパターンを併せた pat_all もマッチしたことになるんですね。


import re


pattern = re.compile(pat_all)


passwd = '12Nana345Saki6^789'


if pattern.match(passwd):
print('有効なパスワードです')
else:
print('危険!危険!')

# 有効なパスワードです


passwd = '12nana345saki6^789' # 大文字を含んでいません


if pattern.match(passwd):
print('有効なパスワードです')
else:
print('危険!危険!')

# 危険!危険!


passwd = '2Na5sa^' # 7 文字です


if pattern.match(passwd):
print('有効なパスワードです')
else:
print('危険!危険!')

# 危険!危険!



さて最後にちょっとだけ補足です。


pat1 と pat5 では「文字集合、および、文字範囲」を表す [ ] シンタックスを使っています。


この [ ] シンタックスの中で利用される '-' 文字は、文字範囲を表すための特殊な意味を持ちます。


例えば、[a-z] であれば、小文字のアルファベット 'a' から 'z' のうちの 1 文字にマッチする、という意味ですよね。


ただし、[ ] の中の先頭、もしくは、最後に置かれている '-' 文字はその特殊な意味を失って、リテラル文字として扱われます


ですから、pat1 と pat5 における [ ] 内の '-' 文字は、特殊文字ではなくて普通の「マイナスサイン」としてのリテラル文字を意味しています。

この投稿をメールでシェアする

0 comments

コメントはまだありません。

コメントを追加する(不適切と思われるコメントは削除する場合があります)