Pythonでテキスト処理を効率化する:`re.fullmatch()` とその代替方法の比較
この関数は、以下の状況で特に役立ちます
- 部分一致ではなく完全一致を見つけたい場合
- テキストの先頭から末尾までパターンが一致しているかどうかを確認したい場合
- 入力テキスト全体が特定の形式に合致しているかどうかを確認したい場合
re.fullmatch() の基本的な使用方法
import re
pattern = r"\d{3}-\d{3}-\d{4}" # 電話番号のパターン
text = "私の電話番号は 123-456-7890 です。"
match = re.fullmatch(pattern, text)
if match:
print("電話番号が見つかりました:", match.group()) # マッチした部分を出力
else:
print("電話番号が見つかりませんでした。")
この例では
- 電話番号を表す正規表現パターン (
r"\d{3}-\d{3}-\d{4}"
) を定義します。 - サンプルテキスト (
"私の電話番号は 123-456-7890 です。"
) を用意します。 re.fullmatch()
を使用して、パターンがテキスト全体に一致するかどうかを確認します。- 一致した場合、電話番号部分を抽出 (
match.group()
) して出力します。 - 一致しない場合は、メッセージを出力します。
re.fullmatch() の応用例
- パスワードの強度をチェックする
- 特定の文字列を含むかどうかをチェックする
- ファイル名の形式をチェックする
- 郵便番号の形式をチェックする
- メールアドレスの形式をチェックする
re.fullmatch() と re.search() の違い
re.search()
は、文字列のどこかにパターンが存在するかどうかを判断します。re.fullmatch()
は、文字列全体がパターンに一致するかどうかを判断します。
- より複雑なパターンマッチングには、
re.findall()
やre.sub()
などの他の関数を使用できます。 - マッチオブジェクトには、マッチした部分に関する情報 (
group()
,start()
,end()
, etc.) が含まれています。 re.fullmatch()
は、re.compile()
でコンパイル済みのパターンオブジェクトを受け取ることもできます。
メールアドレスの形式をチェック
import re
def is_valid_email(email):
"""
与えられた文字列がメールアドレスの形式かどうかを判断します。
"""
pattern = r"[a-zA-Z0-9.+_-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
return re.fullmatch(pattern, email) != None
email1 = "[email protected]"
email2 = "user@invalid"
email3 = "[email protected]"
print(f"{email1} は有効なメールアドレスですか: {is_valid_email(email1)}")
print(f"{email2} は有効なメールアドレスですか: {is_valid_email(email2)}")
print(f"{email3} は有効なメールアドレスですか: {is_valid_email(email3)}")
郵便番号の形式をチェック
import re
def is_valid_zipcode(zipcode):
"""
与えられた文字列が日本の郵便番号の形式かどうかを判断します。
"""
pattern = r"\d{3}-\d{4}"
return re.fullmatch(pattern, zipcode) != None
zipcode1 = "123-4567"
zipcode2 = "1234567"
zipcode3 = "123-456"
print(f"{zipcode1} は有効な郵便番号ですか: {is_valid_zipcode(zipcode1)}")
print(f"{zipcode2} は有効な郵便番号ですか: {is_valid_zipcode(zipcode2)}")
print(f"{zipcode3} は有効な郵便番号ですか: {is_valid_zipcode(zipcode3)}")
ファイル名の形式をチェック
import re
def is_valid_filename(filename):
"""
与えられた文字列が有効なファイル名の形式かどうかを判断します。
"""
pattern = r"[a-zA-Z0-9_\-\.]+$"
return re.fullmatch(pattern, filename) != None
filename1 = "document.txt"
filename2 = "invalid-filename"
filename3 = "filename_with_spaces.txt"
print(f"{filename1} は有効なファイル名ですか: {is_valid_filename(filename1)}")
print(f"{filename2} は有効なファイル名ですか: {is_valid_filename(filename2)}")
print(f"{filename3} は有効なファイル名ですか: {is_valid_filename(filename3)}")
特定の文字列を含むかどうかをチェック
import re
def contains_pattern(text, pattern):
"""
与えられたテキストが特定の文字列を含むかどうかを判断します。
"""
return re.fullmatch(pattern, text) != None
text1 = "Python プログラミングは楽しいです。"
pattern1 = "Python"
pattern2 = "Java"
print(f"{text1} には {pattern1} が含まれていますか: {contains_pattern(text1, pattern1)}")
print(f"{text1} には {pattern2} が含まれていますか: {contains_pattern(text1, pattern2)}")
import re
def is_valid_password(password):
"""
与えられたパスワードが十分な強度かどうかを判断します。
"""
pattern = r"(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#\<span class="math-inline">%\\^&\\\*\\\(\\\)\\\[\\\]\\\{\\\}\\'\\"\\<\\\>\\/\=\\\+\\\-\\\_\]\)\.\{8,\}</span>"
return re.fullmatch(pattern, password) != None
password1 = "Passw0rd123!"
password2 = "password"
password3 = "12345678"
print(f"{password1} は有効なパスワードですか: {is_valid_password(password1)}")
print(f"{password2} は有効なパスワードですか: {is_valid_password(password2)}")
print(f"{password3} は有効なパスワードですか: {is_valid_password(
re.search()
- 欠点:
- 部分一致しか検出できないため、完全一致が必要な場合は不適切
- 複数のパターンが存在する場合、最初のマッチのみを返す
- 利点:
- テキスト内の任意の位置でパターンに一致する部分を見つけられる
re.fullmatch()
よりも柔軟で汎用性が高い
import re
pattern = r"\d{3}-\d{3}-\d{4}"
text = "私の電話番号は 123-456-7890 です。自宅の電話番号は 987-654-3210 です。"
match = re.search(pattern, text)
if match:
print("電話番号が見つかりました:", match.group())
else:
print("電話番号が見つかりませんでした。")
re.findall()
- 欠点:
- 部分一致しか検出できないため、完全一致が必要な場合は不適切
- マッチオブジェクトではなくリストを返すため、
re.fullmatch()
やre.search()
ほど詳細な情報が得られない
- 利点:
- テキスト内にあるすべてのパターンマッチを抽出できる
- 複数のマッチを処理する必要がある場合に便利
import re
pattern = r"\d{3}-\d{3}-\d{4}"
text = "私の電話番号は 123-456-7890 です。自宅の電話番号は 987-654-3210 です。"
matches = re.findall(pattern, text)
if matches:
print("電話番号のリスト:", matches)
else:
print("電話番号が見つかりませんでした。")
文字列操作方法
- 欠点:
- 複雑なパターンには対応できない
- 正規表現ほど柔軟性がない
- 利点:
- シンプルで分かりやすい
- 正規表現よりも高速に処理できる場合がある
text = "私の電話番号は 123-456-7890 です。"
if "-" in text and len(text) == 12:
print("電話番号が見つかりました:", text[text.find("-") - 3:text.find("-") + 6])
else:
print("電話番号が見つかりませんでした。")
サードパーティライブラリ
- 欠点:
re
モジュールほど標準化されていない- インストールや設定が必要になる場合がある
- 利点:
re
モジュールよりも高度な機能を提供するものがある- 特定のタスクに特化したライブラリを使用することで、コードをより簡潔に記述できる場合がある
例
どの代替方法が最適かは、具体的な状況によって異なります。 以下の点を考慮して選択してください。
- サードパーティライブラリの導入に抵抗がないか
- シンプルで分かりやすい方法を望むのか、高度な機能を必要とするのか
- 複数のマッチを処理する必要があるのか
- テキスト全体がパターンに一致しているかどうかを判断したいのか、部分一致でも良いのか
上記以外にも、状況によってはループや条件分岐を用いて独自の方法で実装することも可能です。