Pythonのreモジュールは正規表現を扱うための強力なツールです。正規表現は文字列のパターンをマッチングするための方法で、テキスト内で特定の文字列パターンを検索・照合することができます。本稿では、Pythonのreモジュールの応用といくつかのテクニックについて探ります。
1. reモジュールのインポート
まず、reモジュールをインポートする必要があります:
import re
2. reモジュールによるマッチング
以下の例では、文字列内で特定のパターンを検索する方法を示します:
text = "速い茶色の狐が怠惰な犬の上を跳び越える"
# reモジュールでマッチング
matches = re.findall(r'\b\w{3}\b', text)
print(matches) # 3文字の単語リストを出力
この例では、3文字の単語をマッチングするために\b\w{3}\bという正規表現を使用しています。\bは単語の境界を表し、\w{3}は3文字の文字をマッチングします。re.findall()関数はすべてのマッチング結果を返します。
3. グループの使用
グループは正規表現の強力な機能で、マッチした部分をグループとして処理できます。以下の例では、グループを使用してテキストからメールアドレスを抽出します:
text = "お問い合わせ先: support@example.com, sales@example.com"
# グループを使用してメールアドレスを抽出
emails = re.findall(r'([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})', text)
print(emails) # 抽出されたメールアドレスリストを出力
この例では、([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})がメールアドレスをマッチングする正規表現です。()はメールアドレス全体をグループとして扱い、re.findall()関数がマッチしたメールアドレス部分のみを返します。
4. 文字列の置換
reモジュールには置換機能もあり、正規表現を使用してテキスト内の特定の文字列を置換できます。以下の例では、テキスト内のすべての数字を"X"に置換します:
text = "リンゴが123個とオレンジが456個ある"
# re.sub()関数で数字を"X"に置換
new_text = re.sub(r'\d+', 'X', text)
print(new_text) # 置換後のテキストを出力
この例では、re.sub(r'\d+', 'X', text)が1つ以上の数字をマッチングし、"X"に置換します。
5. コンパイルされた正規表現の使用
大量のテキストを処理する場合、コンパイルされた正規表現を使用するとマッチングの効率が向上します。以下の例では、コンパイルされた正規表現を使用してマッチングします:
pattern = re.compile(r'\bpython\b', re.IGNORECASE)
text = "Pythonは人気のあるプログラミング言語です"
# コンパイルされた正規表現でマッチング
match = pattern.search(text)
if match:
print("見つかりました")
else:
print("見つかりませんでした")
この例では、re.compile()関数が大文字小文字を区別しない正規表現をコンパイルし、search()メソッドでマッチングします。
6. 事前定義された文字クラスの使用
正規表現には特定のタイプの文字をマッチングするための事前定義された文字クラスがあります。以下に一般的な文字クラスとその使用例を示します:
\d:任意の数字文字にマッチングします。\w:任意の文字、数字、アンダースコア文字にマッチングします。\s:任意の空白文字(スペース、タブ、改行など)にマッチングします。
text = "コードは1234で、パスワードはabcd_123です"
# 事前定義された文字クラスで数字と文字のパスワードをマッチング
codes = re.findall(r'\b\w+\b', text)
print(codes) # マッチングしたコードとパスワードリストを出力
7. 量辞の使用
量辞は文字またはグループのマッチング数を指定します。以下に一般的な量辞とその使用例を示します:
*:前の文字を0回以上マッチングします。+:前の文字を1回以上マッチングします。?:前の文字を0回または1回マッチングします。{n}:前の文字をちょうどn回マッチングします。{n,}:前の文字を少なくともn回マッチングします。{n,m}:前の文字を少なくともn回、しかしm回を超えない回数マッチングします。
text = "Pythonプログラミング言語はデータ分析に広く使用されています"
# 量辞で少なくとも2文字の単語をマッチング
words = re.findall(r'\b\w{2,}\b', text)
print(words) # マッチングした単語リストを出力
8. アンカーの使用
アンカーは実際の文字ではなく、文字列の境界をマッチングします。以下に一般的なアンカーとその使用例を示します:
^:文字列の先頭にマッチングします。$:文字列の末尾にマッチングします。\b:単語の境界にマッチングします。
text = "Pythonは初心者と両方の専門家にとって優れた言語です"
# アンカーでPythonで始まる文をマッチング
sentence = re.findall(r'^Python.*', text)
print(sentence) # マッチングした文を出力
9. 貪欲マッチングと非貪欲マッチング
正規表現では、量辞はデフォルトで貪欲であり、可能な限り最長の文字列をマッチングします。しかし、最短の文字列をマッチングしたい場合もあります。量辞の後に?を追加すると非貪欲マッチングになります。
text = "Pythonは強力なプログラミング言語です"
# 貪欲マッチングで"p"から"g"までの内容を検索
greedy_match = re.findall(r'p.*g', text)
# 非貪欲マッチングで"p"から"g"までの内容を検索
non_greedy_match = re.findall(r'p.*?g', text)
print("貪欲マッチング:", greedy_match) # 貪欲マッチング結果を出力
print("非貪欲マッチング:", non_greedy_match) # 非貪欲マッチング結果を出力
10. 後方参照の使用
後方参照は、以前にマッチングした内容を正規表現内で参照できるようにします。これは繰り返しのパターンをマッチングする場合に便利です。
text = "りんご りんご オレンジ オレンジ"
# 後方参照で繰り返しの単語をマッチング
duplicates = re.findall(r'(\b\w+\b) \1', text)
print("繰り返しの単語:", duplicates) # マッチングした繰り返し単語リストを出力
11. 複数行マッチング
単行だけでなく複数行のテキストをマッチングする必要がある場合があります。re.MULTILINEフラグを使用すると、複数行マッチングモードを有効にできます。
text = """Pythonは人気のあるプログラミング言語です。
Web開発、データ分析などに使用されています。
Pythonはシンプルな構文を持ち、学びやすいです。"""
# 複数行マッチングモードで大文字で始まる文をマッチング
sentences = re.findall(r'^[A-Z].*$', text, re.MULTILINE)
print("大文字で始まる文:", sentences) # マッチングした文リストを出力
12. 名前付きグループの使用
複雑な正規表現では、可読性と保守性を向上させるために名前付きグループを使用してマッチング部分を識別できます。
text = "ジョンは5個のリンゴを持っています、メアリーは3個のオレンジを持っています"
# 名前付きグループで名前と果物の数量を抽出
matches = re.findall(r'(?P<name>\w+)は(?P<quantity>\d+)個の\w+を持っています', text)
for match in matches:
print("名前:", match['name'], "- 数量:", match['quantity'])
13. 先読みアサーションの使用
先読みアサーションは、文字列をマッチングする際に文字列の前後の条件を指定できます。これはマッチングした文字列を消費せず、条件のみを指定するために使用されます。
text = "りんご バナナ オレンジ ぶどう"
# 先読みアサーションで"りんご"の後に続くすべての果物をマッチング
result = re.findall(r'(?<=りんご\s)(\w+)', text)
print("'りんご'の後の果物:", result) # マッチングした果物リストを出力
14. 肯定先読みアサーションと否定先読みアサーションの使用
肯定先読みアサーション(?=...)は条件を満たす文字列にマッチングし、否定先読みアサーション(?!)は条件を満たさない文字列にマッチングします。
text = "Pythonは強力なプログラミング言語です"
# 肯定先読みアサーションで"は"を含む単語をマッチング
positive_result = re.findall(r'\b\w+(?= は\b)', text)
# 否定先読みアサーションで"は"を含まない単語をマッチング
negative_result = re.findall(r'\b\w+(?! は\b)', text)
print("肯定先読みアサーション:", positive_result) # マッチングした単語リストを出力
print("否定先読みアサーション:", negative_result) # マッチングした単語リストを出力
15. re.finditer()関数の使用
re.finditer()関数はre.findall()関数に似ていますが、イテレータを返し、マッチングオブジェクトを個別にアクセスできます。
text = "Pythonは強力なプログラミング言語です"
# re.finditer()関数ですべての単語をマッチング
matches_iter = re.finditer(r'\b\w+\b', text)
for match in matches_iter:
print(match.group()) # マッチングした単語を出力
16. re.split()関数の使用
マッチングとテキストパターンの検索に加え、reモジュールにはre.split()関数があり、正規表現パターンに基づいて文字列を分割できます。
text = "りんご,バナナ,オレンジ,ぶどう"
# re.split()関数でカンマに基づいて文字列を分割
fruits = re.split(r',', text)
print("分割された果物リスト:", fruits) # 分割された果物リストを出力
17. re.sub()関数の置換関数パラメータの使用
re.sub()関数の第二引数は関数にすることができ、マッチング結果を処理してから置換できます。
def double(match):
return str(int(match.group(0)) * 2)
text = "数字は1, 2, 3, 4です"
# 置換関数パラメータですべての数字を2倍にする
new_text = re.sub(r'\d+', double, text)
print("置換後のテキスト:", new_text) # 置換後のテキストを出力
18. re.fullmatch()関数の使用
re.fullmatch()関数は、文字列全体が指定されたパターンに完全に一致するかを確認します。
pattern = re.compile(r'\d{4}-\d{2}-\d{2}')
date1 = "2022-01-15"
date2 = "15-01-2022"
# re.fullmatch()関数で日付形式を確認
match1 = pattern.fullmatch(date1)
match2 = pattern.fullmatch(date2)
if match1:
print("日付形式が正しい")
else:
print("日付形式が正しくない")
if match2:
print("日付形式が正しい")
else:
print("日付形式が正しくない")
19. re.IGNORECASEフラグで大文字小文字を区別しないマッチング
正規表現をコンパイルする際、re.IGNORECASEフラグを使用すると大文字小文字を区別しないマッチングができます。
pattern = re.compile(r'python', re.IGNORECASE)
text = "Pythonは強力なプログラミング言語です"
# 大文字小文字を区別しないマッチングで"Python"を検索
match = pattern.search(text)
if match:
print("見つかりました")
else:
print("見つかりませんでした")
20. re.DEBUGフラグで正規表現をデバッグする
正規表現をコンパイルする際、re.DEBUGフラグを使用すると、正規表現のデバッグ情報を出力できます。これにより、その動作原理をよりよく理解できます。
pattern = re.compile(r'\b\w{3}\b', re.DEBUG)
text = "速い茶色の狐が怠惰な犬の上を跳び越える"
# コンパイルされた正規表現のデバッグ情報を出力
pattern.findall(text)