こんにちは、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) # 出力: None2.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()) # 出力: cat3. よく使用するパターン
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@")) # False4. グループの使用
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, 日: 194.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')}") # 出力: 年齢: 305. 文字列の置換
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 dog5.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 FRIENDS6. パフォーマンスの最適化
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.txt7.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

