[Python] 正規表現の使い方 – 基本的なパターンも解説

Pythonで正規表現を使用するには、reモジュールをインポートします。

基本的なパターンとして、.は任意の1文字、^は行の先頭、$は行の末尾を示します。

*は直前の文字が0回以上、+は1回以上、?は0回または1回の出現を意味します。

[]は文字クラスを定義し、[a-z]は小文字のアルファベットを示します。

|はOR条件を表し、()はグループ化に使用されます。

re.search()は文字列内でパターンを検索し、re.match()は文字列の先頭でパターンをチェックします。

re.findall()はすべての一致をリストで返し、re.sub()はパターンに一致する部分を置換します。

この記事でわかること
  • Pythonで正規表現を使用するためのreモジュールの基本的な使い方
  • メタ文字や繰り返しパターン、文字クラスを用いた正規表現の基本パターン
  • re.search()やre.match()などの関数を使ったパターン検索の方法
  • re.findall()やre.finditer()を用いた複数の一致を取得する方法
  • re.sub()やre.subn()を使った文字列の置換方法とその応用例

目次から探す

正規表現とは

正規表現は、文字列のパターンを指定するための特殊な文字列です。

プログラミングにおいて、特定の文字列を検索、置換、抽出するために広く使用されています。

Pythonでは、reモジュールを使用して正規表現を扱うことができます。

正規表現の基本

正規表現は、特定の文字列パターンを表現するための記法です。

以下のような基本的な要素があります。

スクロールできます
要素説明
.任意の1文字を表す
^行の先頭を示す
$行の末尾を示す
*0回以上の繰り返し
+1回以上の繰り返し
?0回または1回の出現
[]文字クラスを定義
()グループ化

これらの要素を組み合わせることで、複雑な文字列パターンを表現することができます。

正規表現の歴史と用途

正規表現は、1950年代に数学者のスティーブン・クレイニーによって初めて定義されました。

その後、Unixの開発において、テキスト処理ツールであるgrepsedなどで広く採用され、プログラミング言語にも組み込まれるようになりました。

用途としては、以下のようなものがあります。

  • テキスト検索と置換
  • データのバリデーション(例:メールアドレスや電話番号の形式チェック)
  • ログファイルの解析
  • Webスクレイピング

Pythonでの正規表現の位置づけ

Pythonでは、正規表現を扱うためにreモジュールが標準ライブラリとして提供されています。

このモジュールを使用することで、文字列の検索、置換、分割などを効率的に行うことができます。

以下は、Pythonで正規表現を使用する基本的な例です。

import re
# 正規表現パターンを定義
pattern = r'\d+'  # 数字の連続を表すパターン
# 検索対象の文字列
text = "Python3はバージョン3.9.1です"
# パターンに一致する部分を検索
matches = re.findall(pattern, text)
print(matches)  # ['3', '3', '9', '1']

この例では、文字列中の数字をすべて抽出しています。

re.findall()関数を使用することで、パターンに一致するすべての部分をリストとして取得できます。

正規表現を使うことで、複雑な文字列操作を簡潔に記述することが可能です。

Pythonで正規表現を使う準備

Pythonで正規表現を使用するためには、標準ライブラリであるreモジュールをインポートする必要があります。

このモジュールには、正規表現を扱うための便利な関数が多数用意されています。

reモジュールのインポート

reモジュールを使用するには、まずPythonスクリプトの中でインポートする必要があります。

インポートは非常に簡単で、以下のように記述します。

import re

この1行をスクリプトの先頭に追加することで、reモジュールのすべての機能を利用できるようになります。

基本的な関数の紹介

reモジュールには、正規表現を扱うための多くの関数が用意されています。

ここでは、特に基本的でよく使われる関数を紹介します。

スクロールできます
関数名説明
re.search()文字列全体を検索し、最初にマッチした部分を返す
re.match()文字列の先頭からマッチするかを確認
re.findall()文字列中のすべてのマッチをリストとして返す
re.finditer()文字列中のすべてのマッチをイテレータとして返す
re.sub()マッチした部分を置換する
re.split()正規表現にマッチした部分で文字列を分割する

re.search()

re.search()は、文字列全体を検索し、最初にマッチした部分を返します。

マッチが見つからない場合はNoneを返します。

import re
pattern = r'Python'
text = "I love Python programming."
match = re.search(pattern, text)
if match:
    print("マッチした部分:", match.group())  # マッチした部分: Python

re.match()

re.match()は、文字列の先頭からマッチするかを確認します。

先頭にマッチしない場合はNoneを返します。

import re
pattern = r'I love'
text = "I love Python programming."
match = re.match(pattern, text)
if match:
    print("先頭にマッチ:", match.group())  # 先頭にマッチ: I love

re.findall()

re.findall()は、文字列中のすべてのマッチをリストとして返します。

import re
pattern = r'\d+'
text = "バージョンは3.9.1です。"
matches = re.findall(pattern, text)
print("すべてのマッチ:", matches)  # すべてのマッチ: ['3', '9', '1']

これらの関数を使うことで、Pythonでの文字列操作が非常に柔軟かつ強力になります。

正規表現を使いこなすことで、複雑な文字列処理を簡潔に行うことができます。

基本的な正規表現パターン

正規表現では、特定の文字列パターンを表現するためにメタ文字や特殊な記号を使用します。

これらを理解することで、より柔軟で強力な文字列操作が可能になります。

メタ文字の説明

メタ文字は、正規表現において特別な意味を持つ文字です。

以下に代表的なメタ文字を紹介します。

任意の文字を表す .

.は任意の1文字を表します。

改行文字を除くすべての文字にマッチします。

import re
pattern = r'c.t'
text = "cat, cut, cot"
matches = re.findall(pattern, text)
print("任意の文字にマッチ:", matches)  # 任意の文字にマッチ: ['cat', 'cut', 'cot']

行の先頭と末尾を示す ^ と $

^は行の先頭を、$は行の末尾を示します。

import re
pattern_start = r'^Hello'
pattern_end = r'world$'
text = "Hello, world"
match_start = re.search(pattern_start, text)
match_end = re.search(pattern_end, text)
print("行の先頭にマッチ:", match_start.group() if match_start else "なし")  # 行の先頭にマッチ: Hello
print("行の末尾にマッチ:", match_end.group() if match_end else "なし")  # 行の末尾にマッチ: world

繰り返しを表すパターン

繰り返しを表すメタ文字を使うことで、特定のパターンが何度も繰り返される文字列にマッチさせることができます。

0回以上の繰り返し *

*は直前の要素が0回以上繰り返されることを示します。

import re
pattern = r'ab*'
text = "a, ab, abb, abbb"
matches = re.findall(pattern, text)
print("0回以上の繰り返しにマッチ:", matches)  # 0回以上の繰り返しにマッチ: ['a', 'ab', 'abb', 'abbb']

1回以上の繰り返し +

+は直前の要素が1回以上繰り返されることを示します。

import re
pattern = r'ab+'
text = "a, ab, abb, abbb"
matches = re.findall(pattern, text)
print("1回以上の繰り返しにマッチ:", matches)  # 1回以上の繰り返しにマッチ: ['ab', 'abb', 'abbb']

0回または1回の出現 ?

?は直前の要素が0回または1回出現することを示します。

import re
pattern = r'ab?'
text = "a, ab, abb, abbb"
matches = re.findall(pattern, text)
print("0回または1回の出現にマッチ:", matches)  # 0回または1回の出現にマッチ: ['a', 'ab', 'ab']

文字クラスとセット

文字クラスを使うことで、特定の文字のセットにマッチさせることができます。

文字クラス []

[]内に指定した文字のいずれか1文字にマッチします。

import re
pattern = r'[aiueo]'
text = "apple, orange, grape"
matches = re.findall(pattern, text)
print("母音にマッチ:", matches)  # 母音にマッチ: ['a', 'e', 'o', 'a', 'e', 'a', 'e']

否定文字クラス [^]

[^]内に指定した文字以外の1文字にマッチします。

import re
pattern = r'[^aiueo]'
text = "apple, orange, grape"
matches = re.findall(pattern, text)
print("母音以外にマッチ:", matches)  # 母音以外にマッチ: ['p', 'p', 'l', ',', ' ', 'r', 'n', 'g', ',', ' ', 'g', 'r', 'p']

グループ化とキャプチャ

グループ化を使うことで、正規表現の一部をまとめて扱うことができます。

グループ化 ()

()を使うと、正規表現の一部をグループ化し、その部分をキャプチャすることができます。

import re
pattern = r'(ab)+'
text = "ababab, ab"
matches = re.findall(pattern, text)
print("グループ化にマッチ:", matches)  # グループ化にマッチ: ['ab', 'ab']

非キャプチャグループ (?:)

(?:)を使うと、グループ化はするがキャプチャはしないグループを作成できます。

import re
pattern = r'(?:ab)+'
text = "ababab, ab"
matches = re.findall(pattern, text)
print("非キャプチャグループにマッチ:", matches)  # 非キャプチャグループにマッチ: ['ababab', 'ab']

これらの基本的なパターンを理解することで、正規表現を使った文字列操作がより効果的に行えるようになります。

Pythonでの正規表現の使用例

Pythonのreモジュールを使用することで、正規表現を使ったさまざまな文字列操作が可能です。

ここでは、具体的な使用例をいくつか紹介します。

パターンの検索

文字列中で特定のパターンを検索するために、re.search()re.match()を使用します。

re.search()の使い方

re.search()は、文字列全体を検索し、最初にマッチした部分を返します。

マッチが見つからない場合はNoneを返します。

import re
pattern = r'Python'
text = "I love Python programming."
match = re.search(pattern, text)
if match:
    print("マッチした部分:", match.group())  # マッチした部分: Python

この例では、文字列中に”Python”という単語が含まれているかを検索し、最初に見つかった部分を出力しています。

re.match()の使い方

re.match()は、文字列の先頭からマッチするかを確認します。

先頭にマッチしない場合はNoneを返します。

import re
pattern = r'I love'
text = "I love Python programming."
match = re.match(pattern, text)
if match:
    print("先頭にマッチ:", match.group())  # 先頭にマッチ: I love

この例では、文字列の先頭が”I love”で始まるかを確認しています。

複数の一致を取得

文字列中のすべてのマッチを取得するために、re.findall()re.finditer()を使用します。

re.findall()の使い方

re.findall()は、文字列中のすべてのマッチをリストとして返します。

import re
pattern = r'\d+'
text = "バージョンは3.9.1です。"
matches = re.findall(pattern, text)
print("すべてのマッチ:", matches)  # すべてのマッチ: ['3', '9', '1']

この例では、文字列中のすべての数字を抽出しています。

re.finditer()の使い方

re.finditer()は、文字列中のすべてのマッチをイテレータとして返します。

各マッチはMatchObjectとして取得できます。

import re
pattern = r'\d+'
text = "バージョンは3.9.1です。"
matches = re.finditer(pattern, text)
for match in matches:
    print("マッチした部分:", match.group())  # マッチした部分: 3, 9, 1

この例では、イテレータを使って各マッチを順に処理しています。

文字列の置換

文字列中の特定のパターンを置換するために、re.sub()re.subn()を使用します。

re.sub()の使い方

re.sub()は、マッチした部分を指定した文字列で置換します。

import re
pattern = r'Python'
replacement = 'Java'
text = "I love Python programming."
new_text = re.sub(pattern, replacement, text)
print("置換後の文字列:", new_text)  # 置換後の文字列: I love Java programming.

この例では、”Python”を”Java”に置換しています。

re.subn()の使い方

re.subn()は、re.sub()と同様に置換を行いますが、置換後の文字列と置換の回数をタプルで返します。

import re
pattern = r'Python'
replacement = 'Java'
text = "I love Python programming. Python is great."
new_text, num_subs = re.subn(pattern, replacement, text)
print("置換後の文字列:", new_text)  # 置換後の文字列: I love Java programming. Java is great.
print("置換の回数:", num_subs)  # 置換の回数: 2

この例では、”Python”を”Java”に置換し、置換が2回行われたことを確認しています。

これらの関数を使うことで、Pythonでの文字列操作が非常に柔軟かつ強力になります。

正規表現を使いこなすことで、複雑な文字列処理を簡潔に行うことができます。

応用例

正規表現は、基本的な文字列操作だけでなく、より複雑なパターンの構築やデータのクリーニング、バリデーションにも応用できます。

ここでは、いくつかの応用例を紹介します。

複雑なパターンの構築

正規表現を使うことで、複雑なパターンを構築し、特定の条件に合致する文字列を抽出することができます。

たとえば、メールアドレスのパターンを構築する場合、以下のようにします。

import re
# メールアドレスのパターン
pattern = r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'
text = "連絡先はexample@example.comです。"
match = re.search(pattern, text)
if match:
    print("メールアドレスにマッチ:", match.group())  # メールアドレスにマッチ: example@example.com

この例では、メールアドレスの一般的な形式にマッチするパターンを構築し、文字列中からメールアドレスを抽出しています。

テキストデータのクリーニング

正規表現を使って、テキストデータから不要な部分を削除したり、フォーマットを整えたりすることができます。

たとえば、テキストからHTMLタグを削除する場合、以下のようにします。

import re
# HTMLタグを削除するパターン
pattern = r'<.*?>'
html_text = "<p>これは<p>HTML</p>の例です。</p>"
clean_text = re.sub(pattern, '', html_text)
print("HTMLタグを削除したテキスト:", clean_text)  # HTMLタグを削除したテキスト: これはHTMLの例です。

この例では、HTMLタグを削除することで、テキストデータをクリーンにしています。

データのバリデーション

正規表現は、データの形式が正しいかどうかを確認するためのバリデーションにも使用できます。

たとえば、電話番号の形式を確認する場合、以下のようにします。

import re
# 電話番号のパターン(例: 123-456-7890)
pattern = r'^\d{3}-\d{3}-\d{4}$'
phone_number = "123-456-7890"
if re.match(pattern, phone_number):
    print("電話番号の形式が正しい")  # 電話番号の形式が正しい
else:
    print("電話番号の形式が正しくない")

この例では、電話番号が指定された形式に合致するかどうかを確認しています。

正規表現を使うことで、データのバリデーションを効率的に行うことができます。

これらの応用例を通じて、正規表現の強力な機能を活用し、さまざまなデータ処理のニーズに対応することができます。

よくある質問

正規表現が遅いと感じるのはなぜ?

正規表現が遅いと感じる理由はいくつかあります。

まず、複雑なパターンを使用すると、バックトラッキングが多く発生し、処理時間が増加することがあります。

特に、ネストされた繰り返しや曖昧なパターンは、パフォーマンスに影響を与えることがあります。

また、大量のデータを処理する場合、正規表現の処理自体がボトルネックになることもあります。

最適化のためには、パターンをシンプルにし、必要に応じて部分的に正規表現を使うことが推奨されます。

re.match()とre.search()の違いは?

re.match()re.search()は、どちらも正規表現を使って文字列を検索するための関数ですが、その動作には違いがあります。

re.match()は文字列の先頭からパターンがマッチするかを確認します。

つまり、文字列の最初の部分がパターンに一致する場合にのみマッチします。

一方、re.search()は文字列全体を検索し、最初にマッチした部分を返します。

したがって、文字列のどの位置にパターンが現れてもマッチします。

例:re.match(r'abc', 'abcde')はマッチしますが、re.match(r'abc', 'xabcde')はマッチしません。

re.search(r'abc', 'xabcde')はマッチします。

正規表現で日本語を扱うにはどうすればいい?

正規表現で日本語を扱うためには、Unicodeをサポートする必要があります。

Pythonの正規表現はデフォルトでUnicodeをサポートしているため、日本語を含む文字列を直接扱うことができます。

ただし、文字クラスを使用する際には注意が必要です。

たとえば、[a-zA-Z]のような文字クラスは英字のみを対象とするため、日本語を含める場合は[\u3040-\u30FF](ひらがなとカタカナ)や[\u4E00-\u9FFF](漢字)などのUnicode範囲を指定することができます。

また、正規表現パターンを記述する際には、Pythonの文字列リテラルでr''を使用してエスケープシーケンスを無効にすることをお勧めします。

まとめ

この記事では、Pythonにおける正規表現の基本的な使い方から応用例までを詳しく解説しました。

正規表現の基本パターンやreモジュールの関数を活用することで、文字列操作がより効率的に行えることがわかります。

これを機に、実際のプロジェクトで正規表現を活用し、より高度なデータ処理やテキスト解析に挑戦してみてください。

  • URLをコピーしました!
目次から探す