【Python】正規表現:reモジュールで文字列を効率的に処理する

Python
この記事は約12分で読めます。

こんにちは、JS2IIUです。
正規表現(Regular Expression)は、文字列の検索やパターンマッチングを行うための強力なツールです。Pythonではreモジュールを使用することで、複雑な文字列処理を効率的に実行することができます。今回もよろしくお願いします。

1. reモジュールの基本

まず最初に、reモジュールをインポートする必要があります:

Python
import re

主な関数

reモジュールには以下の重要な関数があります:

  • re.match(): 文字列の先頭からパターンマッチングを行う
  • re.search(): 文字列全体からパターンを検索する
  • re.findall(): すべてのマッチを検索してリストとして返す
  • re.sub(): パターンマッチした部分を置換する
  • re.split(): パターンで文字列を分割する

2. パターンマッチングの基本

2.1 単純な文字列マッチング

Python
# 基本的な文字列マッチング
text = "Hello, Python!"
result = re.search(r"Python", text)
print(result.group())  # 出力: Python

# マッチしない場合
result = re.search(r"Java", text)
print(result)  # 出力: None

2.2 メタ文字の使用

Python
# ドット(.): 任意の1文字にマッチ
text = "cat, bat, rat"
result = re.findall(r".at", text)
print(result)  # 出力: ['cat', 'bat', 'rat']

# アスタリスク(*): 直前の文字の0回以上の繰り返し
text = "ca*t"
result = re.match(r"ca*t", text)
print(result.group())  # 出力: cat

3. よく使用するパターン

3.1 数字のマッチング

Python
# 数字にマッチする
text = "私の電話番号は123-4567-8901です"
result = re.search(r"\d{3}-\d{4}-\d{4}", text)
print(result.group())  # 出力: 123-4567-8901

# 数字以外にマッチする
text = "ABC123"
result = re.findall(r"\D+", text)
print(result)  # 出力: ['ABC']

3.2 メールアドレスのバリデーション

Python
def is_valid_email(email):
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return bool(re.match(pattern, email))

# テスト
print(is_valid_email("user@example.com"))  # True
print(is_valid_email("invalid.email@"))    # False

4. グループの使用

4.1 キャプチャグループ

Python
# 括弧()でグループを作成
text = "2024年2月19日"
pattern = r"(\d{4})(\d{1,2})(\d{1,2})"
result = re.match(pattern, text)

if result:
    year = result.group(1)
    month = result.group(2)
    day = result.group(3)
    print(f"年: {year}, 月: {month}, 日: {day}")
    # 出力: 年: 2024, 月: 2, 日: 19

4.2 名前付きグループ

Python
# ?P<name>でグループに名前をつける
text = "名前: 山田太郎, 年齢: 30歳"
pattern = r"名前: (?P<name>.*?), 年齢: (?P<age>\d+)"
result = re.search(pattern, text)

if result:
    print(f"名前: {result.group('name')}")  # 出力: 名前: 山田太郎
    print(f"年齢: {result.group('age')}")   # 出力: 年齢: 30

5. 文字列の置換

5.1 基本的な置換

Python
# 単純な置換
text = "Hello, World!"
result = re.sub(r"World", "Python", text)
print(result)  # 出力: Hello, Python!

# 複数箇所の置換
text = "cat and cat"
result = re.sub(r"cat", "dog", text)
print(result)  # 出力: dog and dog

5.2 条件付き置換

Python
def convert_case(match):
    word = match.group(0)
    return word.upper() if len(word) > 3 else word

text = "The cat and dog are friends"
result = re.sub(r'\w+', convert_case, text)
print(result)  # 出力: THE cat and dog ARE FRIENDS

6. パフォーマンスの最適化

6.1 パターンのコンパイル

頻繁に使用するパターンは、コンパイルして再利用することでパフォーマンスが向上します:

Python
# パターンのコンパイル
pattern = re.compile(r'\d+')

# 複数回の使用
text1 = "123 456"
text2 = "789 012"

print(pattern.findall(text1))  # 出力: ['123', '456']
print(pattern.findall(text2))  # 出力: ['789', '012']

6.2 最適化のヒント

  • 可能な限り具体的なパターンを使用する
  • 過度な後方参照を避ける
  • 不要な括弧の使用を控える
  • 適切なフラグを使用する(re.VERBOSE, re.IGNORECASE など)

7. よくある間違いと注意点

7.1 メタ文字のエスケープ

Python
# 正しいエスケープ
text = "price: $100"
result = re.search(r'\$\d+', text)
print(result.group())  # 出力: $100

# ドット文字のエスケープ
text = "file.txt"
result = re.search(r'file\.txt', text)
print(result.group())  # 出力: file.txt

7.2 貪欲な量指定子と非貪欲な量指定子

Python
text = "<p>First paragraph</p><p>Second paragraph</p>"

# 貪欲なマッチング
greedy = re.findall(r'<p>.*</p>', text)
print(greedy)  # 出力: ['<p>First paragraph</p><p>Second paragraph</p>']

# 非貪欲なマッチング
non_greedy = re.findall(r'<p>.*?</p>', text)
print(non_greedy)  # 出力: ['<p>First paragraph</p>', '<p>Second paragraph</p>']

8. 貪欲マッチングと非貪欲マッチングの詳細説明

正規表現における貪欲(greedy)マッチングと非貪欲(non-greedy)マッチングの違いを理解することは、効果的なパターンマッチングを行う上で非常に重要です。

8.1 貪欲マッチングとは

貪欲マッチングは、量指定子(*, +, ?, {n,m})がデフォルトで持つ動作で、「できるだけ多くの文字にマッチする」という特徴があります。

Python

コメント

タイトルとURLをコピーしました