Python 正規表現:決定版ガイド

tags: python, regex, tutorial, programming


Python 正規表現:決定版ガイド

10,000行に及ぶログファイルを目の前にして、すべてのメールアドレス、IPアドレス、タイムスタンプを数秒で抽出する必要があると想像してみてください。手動の文字列スライスやネストしたループで行うと、永遠に時間がかかり、エッジケースで簡単に破綻するでしょう。しかし、Python 正規表現を使えば、1行のエレガントなコードでこの問題を解決できます。正規表現は単なる開発者のスーパーパワーではなく、パターンマッチング、テキスト検証、データ抽出のための究極のツールです。一緒にマスターしていきましょう。

Pythonの re モジュール入門

複雑なパターンを書く前に、適切なツールをインポートする必要があります。Pythonはビルトインの re モジュールを通じて正規表現を扱います。このモジュールは軽量で強力であり、すべての標準Pythonインストールで利用可能です。

import re

Enter fullscreen mode Exit fullscreen mode

最初に守るべき黄金律:パターンには常にraw文字列を使用することです。文字列の先頭に r を付ける(例:r"\d+")ことで、正規表現エンジンがパターンを見たときにPythonがバックスラッシュをエスケープ文字として解釈するのを防ぎます。これにより、\n が改行文字ではなくリテラルの「バックスラッシュ-n」パターンになってしまうような微妙なバグを回避できます。

日常的に使うコア正規表現関数

re モジュールにはいくつかの関数がありますが、時間の90%で使用するのは次の4つです:

re.search()

文字列全体をスキャンし、パターンが見つかった場合は matchオブジェクト を返し、見つからなかった場合は None を返します。条件が存在するかを確認するのに最適です。

re.match()

文字列の先頭でのみパターンが一致するかを確認します。テキストの先頭に余分な空白や無関係な文字がある場合、パターンが後で存在していても match() は失敗する可能性があります。

re.findall()

重複しないすべてのマッチのリスト を返します。これは文書からすべての電話番号を抽出するなど、データを抽出するのに最適です。

re.sub()

パターンのすべてのインスタンスを検索し、新しい文字列に置換します。データのクリーニングや入力のサニタイズに使用します。

基本パターンと特殊文字

正規表現のパターンは、通常の文字(a5! など)とルールを定義するメタ文字から構築されます。今日必要な基本要素は次のとおりです:

メタ文字 意味
. 改行以外の任意の1文字
^ 文字列の開始
$ 文字列の終了
\d 任意の数字(0–9)
\w 任意の単語文字(文字、数字、アンダースコア)
\s 任意の空白文字(スペース、タブ、改行)

例として、r"\d{3}-\d{4}"555-1234 のような米国の電話番号形式にマッチします。

量指定子:繰り返しの制御

文字の「1つ以上」や「0個以上」にマッチする必要があることがよくあります。量指定子がこれを扱います:

  • * : 0回以上(例:ab*aababb にマッチ)
  • + : 1回以上(例:ab+ababb にマッチするが a にはマッチしない)
  • ? : 0回または1回(例:ab?a または ab にマッチ)
  • {n} : ちょうど n 回(例:\d{4} はちょうど4桁の数字にマッチ)
  • {n,m} : n 回以上 m 回以下

アンカーと境界

アンカーを使用すると、内容だけでなく位置に基づいてマッチさせることができます:

  • ^pattern : パターンが開始位置にある場合のみマッチ。
  • pattern$ : パターンが終了位置にある場合のみマッチ。
  • \b : 単語境界(\bcat\b のように単語全体をマッチさせて「category」とマッチしないようにするのに便利)。

実践的な動作例

すべてをまとめてみましょう。乱雑なログ文字列があり、すべてのメールアドレスを抽出して [REDACTED] に置換し、見つかった数をカウントする必要があるとします。

import re

log_text = """
User [email protected] logged in from 192.168.1.1.
Error: Invalid email user@@test.com. Contact [email protected].
Another user: [email protected] tried again.
"""

# 1. メールパターンを定義
email_pattern = r"[a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+\.[a-zA-Z]{2,}"

# 2. すべてのメールを検索
emails = re.findall(email_pattern, log_text)
print(f"Found {len(emails)} emails: {emails}")

# 3. 置換
cleaned_log = re.sub(email_pattern, "[REDACTED]", log_text)
print("\nCleaned Log:")
print(cleaned_log)

Enter fullscreen mode Exit fullscreen mode

出力:

Found 3 emails: ['[email protected]', '[email protected]', '[email protected]']

Cleaned Log:

User [REDACTED] logged in from 192.168.1.1.
Error: Invalid email user@@test.com. Contact [REDACTED].
Another user: [REDACTED] tried again.

Enter fullscreen mode Exit fullscreen mode

user@@test.com がパターンに違反(@ 記号が2つある)ため無視されたことに注目してください。これが精密な正規表現の力です:ノイズを自動的にフィルタリングします。

高度なテクニック:グループとルックアラウンド

基本を理解したら、グループ ( ) を使用してマッチの一部をキャプチャすることを探求しましょう。例:r"(\d{4})-(\d{2})-(\d{2})" は日付を年、月、日ごとに分割します。

(?=...)(肯定的な先読み)のようなルックアラウンドを使用すると、他のパターンが続く場合にのみパターンをマッチさせ、結果に2番目の部分を含めません。これらは複雑な検証に強力ですが、使いすぎるとパフォーマンスが低下する可能性があります。

パフォーマンスのヒントとベストプラクティス

正規表現は高速ですが、書き方が悪いと遅くなることがあります。効率を保つ方法は次のとおりです:

  • パターンをコンパイルして再利用: pattern = re.compile(r"\d+") としてから pattern.findall(text)
  • シンプルに始める:パターンを段階的に構築し、小さな入力でテスト。
  • 正規表現の過剰使用を避ける.split().replace() のようなシンプルな文字列メソッドが機能する場合はそれを使用。正規表現は複雑なパターン用であり、すべての文字列タスク用ではありません。
  • 徹底的にテストregex101.com のようなツールを使用してマッチを視覚化し、エッジケースをデバッグ。

重要なポイント

  • エスケープの問題を避けるために常にraw文字列r"pattern")を使用。
  • 4つのコア関数をマスター:search()match()findall()sub()
  • 繰り返しを制御するために量指定子*+?{n})を使用。
  • 位置に基づくマッチングのために ^$ でパターンをアンカー。
  • 再利用する場合はパフォーマンスのためにコンパイル
  • デプロイ前に実世界のデータでパターンをテスト

正規表現は練習で上達するスキルです。今日、小さな問題を1つ解決することから始めてみましょう:メールアドレスの検証、電話番号の抽出、またはCSV列のクリーニング。一度、正規表現が乱雑なテキストを構造化されたデータに変換する様子を見れば、手動の文字列解析に戻ることはないでしょう。

レベルアップする準備はできましたか? 乱雑なテキストファイルを取得し、必要なデータを抽出する正規表現パターンを書き、Dev.toのコメントでパターンを共有しましょう。一緒に正規表現ウィザードのコミュニティを構築しましょう!


この記事が役に立ったと思ったら、コーヒーをおごる ☕ ことを検討してください — これらの記事を継続する助けになります!

また、私のAIツールコレクションもチェックしてください:AI 次元世界 — 開発者向けの無料AIツール。