検索ガイド -Search Guide-

単語と単語を空白で区切ることで AND 検索になります。
例: python デコレータ ('python' と 'デコレータ' 両方を含む記事を検索します)
単語の前に '-' を付けることで NOT 検索になります。
例: python -デコレータ ('python' は含むが 'デコレータ' は含まない記事を検索します)
" (ダブルクオート) で語句を囲むことで 完全一致検索になります。
例: "python data" 実装 ('python data' と '実装' 両方を含む記事を検索します。'python data 実装' の検索とは異なります。)
img_for_tre_tron

Tré Thộn を食べたことがありますか?
ベトナム・ビンズオン滞在中の方は是非注文して食べてみて!
絶対に美味しいです!
ホーチミン市内へも配達可能です。お問い合わせください。

Have you ever had "Tré Thộn" before?
If you're living at Bình Dương in Vietnam, you "must" try to order and eat it.
I'm sure you're very surprised how delicious it is!!
If you're in Hồ Chí Minh, you have a chance to get it too. Please call!!
>>

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

Published 2020年9月11日20:20 by mootaro23

SUPPORT UKRAINE

- Your indifference to the act of cruelty can thrive rogue nations like Russia -

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


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


ここでは「十分に安全」なパスワード ( 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 における [ ] 内の '-' 文字は、特殊文字ではなくて普通の「マイナスサイン」としてのリテラル文字を意味しています。
この記事に興味のある方は次の記事にも関心を持っているようです...
- People who read this article may also be interested in following articles ... -
【 Python + Regular Expressions 】正規表現の 先読み ( look ahead; ?=expression ) 機能を使いこなそう!
【 Effective Python, 2nd Edition 】プログラムを並列処理 ( concurrency ) パターンへ移行するタイミングとツールを考えるシリーズ 第 6 回 - コルーチン ( coroutines ) を利用して数多くのブロッキング I/O を並列処理する fan-out、fan-in パターンを実現しよう、の巻
【Python 雑談・雑学 + coding challenge】文字列中の数字を抜き出して桁区切りをつけよう! 正規表現 (regular expression ) を使うと「えっ!?」っていうくらい簡単ですょ。lookahead と negative lookahead を使います。
Python coding challenge - linked list の奇数番目のノードを前半にまとめ、その後ろに偶数番目のノードを繋げよう!
【 Using Asyncio in Python 】Python における asyncio を利用した非同期プログラム ( asynchronous programming ) の勉強を継続する前に、今一度スレッド ( thread ) についてのちょっとした復習ノート、まとめてみた
Practical Python Design Patterns - Python で学ぶデザインパターン: The Chain of Responsibility Pattern - Part. 3 「WSGI サーバーのセットアップ part 2: Postman を利用した API エンドポイントのテスト」の巻
Practical Python Design Patterns - Python で学ぶデザインパターン: The Decorator Pattern - Part. 3 「クラスを修飾するデコレーター & クロージャークラス」の巻 🔒