Pythonで文字列を操作していると、「あるパターンに一致する部分をまとめて置き換えたい」という場面によく出くわします。
そんなときに力を発揮するのが、正規表現(regex)を使った置換処理re.sub()
です。
replace()
では対応できないような、より柔軟な条件付きの文字列置換も、re.sub()
ならスマートに実現可能です。
本記事では、Pythonのre.sub()
の使い方から、よくある活用例、注意点までを分かりやすく解説します。
re.sub()の基本構文と仕組み

re.sub()とは?
re.sub()
は、Pythonの標準ライブラリre
に含まれる関数で、正規表現にマッチする文字列を指定の文字列で置換します。
まずはインポート
import re
基本の書き方
構文
re.sub(pattern, repl, string, count=0, flags=0)
パラメータの説明
pattern
:置換対象となる正規表現のパターンrepl
:置き換える文字列string
:処理対象の文字列count
:置換する最大回数(0の場合はすべて置換)flags
:検索オプション(例:re.IGNORECASE
)
基本例:単純な置換
コード例
import re
text = "Python is easy. Python is powerful."
result = re.sub("Python", "Java", text)
print(result)
結果
Java is easy. Java is powerful.
説明:文字列中の「Python」をすべて「Java」に置き換えています。
replace()との違い
replace()
の場合
text = "Python is easy. Python is powerful."
result = text.replace("Python", "Java")
print(result) # Java is easy. Java is powerful.
re.sub()
の場合
import re
text = "Python is easy. Python is powerful."
result = re.sub("Python", "Java", text)
print(result) # Java is easy. Java is powerful.
一見同じですが…
replace()
:完全一致のみre.sub()
:パターンマッチング(正規表現)が使える
置換回数を制限する
コード例
import re
text = "cat cat cat dog"
result = re.sub("cat", "mouse", text, count=2)
print(result)
結果
mouse mouse cat dog
説明:count=2
により、最初の2つの「cat」のみが置換されます。
まとめ:re.sub()
の基本的な書き方が分かったところで、次は正規表現の活用による柔軟な置換について掘り下げていきます。
正規表現を使った高度な置換

数字のパターンを置換
コード例
import re
text = "User123 scored 98 points."
result = re.sub(r"\d+", "#", text)
print(result)
結果
User# scored # points.
説明:
\d+
:1つ以上の連続した数字にマッチr"..."
:生文字列(後で詳しく説明)
メールアドレスをマスクする
コード例
import re
text = "連絡先: info@example.com, support@test.org"
result = re.sub(r"\S+@\S+\.\S+", "[メール非表示]", text)
print(result)
結果
連絡先: [メール非表示], [メール非表示]
説明:
\S+
:空白以外の文字が1つ以上@
:アットマーク\.
:ドット(エスケープが必要)
電話番号の形式を統一
コード例
import re
text = "電話: 090-1234-5678, 03-9876-5432"
result = re.sub(r"(\d{2,4})-(\d{4})-(\d{4})", r"\1.\2.\3", text)
print(result)
結果
電話: 090.1234.5678, 03.9876.5432
説明:
(\d{2,4})
:2〜4桁の数字をグループ化\1
,\2
,\3
:キャプチャしたグループを参照
HTMLタグを削除
コード例
import re
html = "<p>こんにちは<br>世界</p>"
result = re.sub(r"<[^>]+>", "", html)
print(result)
結果
こんにちは世界
説明:
<[^>]+>
:<
で始まり>
で終わる、間に>
以外の文字が1つ以上
単語の境界を利用した置換
コード例
import re
text = "cat catastrophe scattered"
# 単語の境界を使って「cat」のみを置換
result = re.sub(r"\bcat\b", "dog", text)
print(result)
結果
dog catastrophe scattered
説明:
\b
:単語境界- 完全な単語「cat」のみがマッチし、「catastrophe」の一部は置換されない
まとめ:正規表現を使うことで、単なる文字列の一致を超えてパターン認識に基づいた置換が可能になります。次は、関数を使った動的な置換を紹介します。
関数を使って置換をカスタマイズする

基本的な関数の使い方
re.sub()
の2番目の引数に関数を渡すことで、マッチした内容に応じて置換の方法を動的に変更できます。
コード例
import re
def to_upper(match):
"""マッチした文字列を大文字に変換"""
return match.group(0).upper()
text = "hello world python"
result = re.sub(r"\b\w+\b", to_upper, text)
print(result)
結果
HELLO WORLD PYTHON
説明:
match.group(0)
:マッチした文字列全体を取得\b\w+\b
:単語境界に囲まれた1つ以上の単語文字
数字を2倍にする
コード例
import re
def double_number(match):
"""マッチした数字を2倍にする"""
number = int(match.group(0))
return str(number * 2)
text = "5個のりんごと3個のオレンジ"
result = re.sub(r"\d+", double_number, text)
print(result)
結果
10個のりんごと6個のオレンジ
より複雑な例:単語の長さで処理を変える
コード例
import re
def process_word(match):
"""単語の長さに応じて処理を変える"""
word = match.group(0)
if len(word) <= 3:
return word.upper() # 短い単語は大文字
else:
return word.lower() # 長い単語は小文字
text = "The Quick Brown Fox Jumps"
result = re.sub(r"\b\w+\b", process_word, text)
print(result)
結果
THE quick brown FOX jumps
グループを使った高度な処理
コード例
import re
def format_date(match):
"""日付の形式を変換"""
year = match.group(1)
month = match.group(2)
day = match.group(3)
return f"{year}年{month}月{day}日"
text = "今日は2025-06-05です"
result = re.sub(r"(\d{4})-(\d{2})-(\d{2})", format_date, text)
print(result)
結果
今日は2025年06月05日です
説明:
(\d{4})
、(\d{2})
:それぞれがグループとしてキャプチャされるmatch.group(1)
、match.group(2)
:各グループにアクセス
条件付き置換
コード例
import re
def conditional_replace(match):
"""条件に応じて置換を決める"""
word = match.group(0)
if word.startswith('P'):
return 'Java'
elif word.startswith('J'):
return 'Python'
else:
return word
text = "Python Java C++ JavaScript"
result = re.sub(r"\b[A-Z]\w*", conditional_replace, text)
print(result)
結果
Java Python C++ Python
まとめ:re.sub()
に関数を渡すことで、単なる置換を超えて、内容に応じた柔軟な処理が可能になります。最後に、よくあるミスや注意点を紹介します。
re.sub()を使う上での注意点とコツ

生文字列(raw string)を使う
問題のあるコード
import re
# バックスラッシュが正しく解釈されない可能性
text = "test\nstring"
result = re.sub("\n", " ", text) # 動くが推奨されない
推奨されるコード
import re
text = "test\nstring"
result = re.sub(r"\n", " ", text) # r"..." を使用
print(repr(result)) # 'test string'
説明:r"..."
(生文字列)を使うことで、バックスラッシュが正規表現として正しく解釈されます。
大文字小文字を無視する
コード例
import re
text = "Python python PyThOn PYTHON"
result = re.sub("python", "Java", text, flags=re.IGNORECASE)
print(result)
結果
Java Java Java Java
説明:flags=re.IGNORECASE
により、大文字小文字を区別せずにマッチします。
よくあるエラーと対処法
エラー1:意図しない部分がマッチしてしまう
問題のあるコード
import re
text = "cats and dogs"
result = re.sub("cat", "mouse", text)
print(result) # mouseS and dogs(不適切)
修正後
import re
text = "cats and dogs"
result = re.sub(r"\bcat\b", "mouse", text)
print(result) # cats and dogs(catは単語として存在しない)
# または、複数形も考慮
result = re.sub(r"\bcats?\b", "mouse", text)
print(result) # mouse and dogs
エラー2:特殊文字のエスケープ忘れ
問題のあるコード
import re
text = "価格: $100.50"
result = re.sub("$", "¥", text) # $は正規表現では行末を意味する
print(result) # 期待通りに動かない
修正後
import re
text = "価格: $100.50"
result = re.sub(r"\$", "¥", text) # エスケープが必要
print(result) # 価格: ¥100.50
エラー3:グループ参照の間違い
問題のあるコード
import re
text = "2025-06-05"
result = re.sub(r"(\d{4})-(\d{2})-(\d{2})", r"\3/\2/\1", text)
print(result) # 05/06/2025(日/月/年の順)
意図したコード
import re
text = "2025-06-05"
result = re.sub(r"(\d{4})-(\d{2})-(\d{2})", r"\2/\3/\1", text)
print(result) # 06/05/2025(月/日/年の順)
パフォーマンスを考慮した使い方
同じパターンを何度も使う場合
非効率な方法
import re
texts = ["text1", "text2", "text3"] * 1000
results = []
for text in texts:
result = re.sub(r"\d+", "#", text) # 毎回コンパイル
results.append(result)
効率的な方法
import re
# パターンを事前にコンパイル
pattern = re.compile(r"\d+")
texts = ["text1", "text2", "text3"] * 1000
results = []
for text in texts:
result = pattern.sub("#", text) # コンパイル済みを再利用
results.append(result)
実践的な使用例
ログファイルの整形
コード例
import re
def clean_log_line(match):
"""ログの不要な情報を削除"""
timestamp = match.group(1)
level = match.group(2)
message = match.group(3)
# DEBUGレベルは除外
if level == "DEBUG":
return ""
return f"[{timestamp}] {level}: {message}"
log_text = """
2025-06-05 10:00:01 INFO User logged in
2025-06-05 10:00:02 DEBUG Database query executed
2025-06-05 10:00:03 ERROR Connection failed
"""
result = re.sub(
r"(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) (\w+) (.+)",
clean_log_line,
log_text
)
print(result)
HTMLエスケープ
コード例
import re
def html_escape(match):
"""HTMLの特殊文字をエスケープ"""
char = match.group(0)
escape_dict = {
'<': '<',
'>': '>',
'&': '&',
'"': '"',
"'": '''
}
return escape_dict.get(char, char)
text = '<div>Hello "World" & Friends</div>'
result = re.sub(r'[<>&"\']', html_escape, text)
print(result)
# <div>Hello "World" & Friends</div>
よく使うパターン集
用途 | パターン | 例 |
---|---|---|
数字 | r"\d+" | re.sub(r"\d+", "#", text) |
メールアドレス | r"\S+@\S+\.\S+" | re.sub(r"\S+@\S+\.\S+", "[email]", text) |
HTMLタグ | r"<[^>]+>" | re.sub(r"<[^>]+>", "", html) |
空白の正規化 | r"\s+" | re.sub(r"\s+", " ", text) |
電話番号 | r"\d{2,4}-\d{4}-\d{4}" | re.sub(r"(\d+)-(\d+)-(\d+)", r"\1.\2.\3", text) |
まとめ:re.sub()で文字列処理をマスターしよう!
重要なポイント
基本的な使い方
re.sub(pattern, repl, string)
で基本的な置換- 正規表現を使ってパターンマッチングが可能
count
パラメータで置換回数を制限できる
応用的な使い方
- 関数を渡して動的な置換が可能
- グループキャプチャで部分的な情報を活用
- フラグを使って大文字小文字を無視などの条件設定
注意すべきポイント
- 生文字列(
r"..."
)を使用してエスケープ問題を回避 - 特殊文字は適切にエスケープする
- パフォーマンスを考慮してパターンをコンパイル
使い分けガイド
用途 | 推奨方法 | 理由 |
---|---|---|
単純な文字列置換 | str.replace() | 高速で分かりやすい |
パターンベースの置換 | re.sub() | 柔軟性が高い |
動的な置換 | re.sub() + 関数 | 条件に応じた処理が可能 |
大量データの処理 | re.compile() + sub() | パフォーマンスが良い |
実践での活用場面
データクレンジング
- ログファイルの整形
- HTMLタグの除去
- 不要な文字の削除
フォーマット変換
- 日付形式の統一
- 電話番号の形式変更
- 通貨記号の変換
セキュリティ対策
- 個人情報のマスキング
- HTMLエスケープ処理
- SQLインジェクション対策
コメント