mei_13のPython講座 ロゴ

【解説】Pythonの正規表現で文字列を高度に置換する:re.sub()の基礎から応用まで




Pythonの正規表現で文字列を高度に置換する:re.sub()の基礎から応用まで


Yukiのアイコン
【Yuki】 Hirokiくん、こんにちは。少し夜も更けて静かになってきましたね...。わたし、こういう静かな時間の方が、コードの細かい部分に集中できる気がして好きなんです。今日は、Pythonで文字列の置換を自由自在に操るための強力なツール、re.sub() について一緒に勉強していきましょう。


Hirokiのアイコン
【Hiroki】 Yukiさん、こんばんは!はい、よろしくお願いします。文字列の置換といえば、普通の replace() メソッドは使ったことがあるんですけど、正規表現を使う re.sub() は難しそうなイメージがあって...。


Yukiのアイコン
【Yuki】 そうですね、確かに正規表現そのものが少し複雑に見えるかもしれません。でも、re.sub() をマスターすると、単純な置換では不可能な、「特定のパターンに一致する部分だけを書き換える」といった高度な操作が簡単にできるようになるんですよ。まずは基本の形から見ていきましょう。

re.sub()の基本的な使い方


Yukiのアイコン
【Yuki】 re.sub() は Python の re モジュールに含まれる関数です。基本的な構文は、re.sub(パターン, 置換文字列, 対象の文字列) となります。簡単な例を書いてみますね。

import re

text = "僕の好きな果物は、りんごとバナナです。"
# 「りんご」か「バナナ」を「フルーツ」に置換します
result = re.sub(r"りんご|バナナ", "フルーツ", text)

print(result)


Hirokiのアイコン
【Hiroki】 あ、これなら僕にもわかります。りんご|バナナ というのが、「りんご、またはバナナ」という意味の正規表現なんですね?


Yukiのアイコン
【Yuki】 その通りです。replace() だと「りんご」を置換して、その結果に対してさらに「バナナ」を置換するという二段階の手順が必要ですが、re.sub() なら一度に指定できるんです。ちなみに、正規表現のパターンの前にある r は「ロウ文字列(raw string)」を意味していて、バックスラッシュをそのまま扱えるようにするための、正規表現ではお決まりの書き方ですね。

特殊な文字クラスを使った置換


Hirokiのアイコン
【Hiroki】 もう少し複雑なこともできるんですか?


Yukiのアイコン
【Yuki】 ええ、例えば「数字だけをすべて『X』に隠したい」といった場合にも便利です。

import re

text = "僕の学籍番号は 2023-0456-789 です。"
# \d は数字を意味します
result = re.sub(r"\d", "X", text)

print(result)
# 出力: 僕の学籍番号は XXXX-XXXX-XXX です。


Yukiのアイコン
【Yuki】 このように、メタ文字と呼ばれる記号を使うことで、具体的な文字ではなく「文字の種類」をターゲットにできるのが re.sub() の強みだと思います...。

置換回数の制限とフラグの活用


Hirokiのアイコン
【Hiroki】 全部置換するんじゃなくて、最初の1回だけ置換したい、という時はどうすればいいんでしょうか?


Yukiのアイコン
【Yuki】 その場合は、第4引数の count を使います。デフォルトは 0 で「すべて置換」という意味ですが、ここに数字を入れることで回数を制限できるんです。また、第5引数の flags を使うと、大文字小文字を区別しないといった設定も可能です。

import re

text = "Apple, apple, APPLE!"
# count=2 で最初の2つだけ置換
# re.IGNORECASE で大文字小文字を無視
result = re.sub(r"apple", "orange", text, count=2, flags=re.IGNORECASE)

print(result)
# 出力: orange, orange, APPLE!


Hirokiのアイコン
【Hiroki】 なるほど、flags を使えばわざわざパターンの中に大文字小文字の両方を書かなくていいから、スマートですね。

キャプチャグループを利用した高度な置換


Yukiのアイコン
【Yuki】 ここからが re.sub() の本当の面白さだとわたしは思っています。パターンの中で () を使う「グループ化(キャプチャ)」を利用すると、マッチした内容の一部を置換後の文字列に再利用できるんです。


Hirokiのアイコン
【Hiroki】 マッチした内容を使い回す...?どういうことですか?


Yukiのアイコン
【Yuki】 例えば、日付の形式を「2024-05-20」から「2024年05月20日」に変換したいとします。この場合、数字の部分はそのまま残して、記号だけを変えたいですよね。

import re

text = "今日は 2024-05-20 です。"
# (\d{4}), (\d{2}), (\d{2}) でそれぞれグループ化
pattern = r"(\d{4})-(\d{2})-(\d{2})"
# \1, \2, \3 でグループ化した内容を参照
replacement = r"\1年\2月\3日"

result = re.sub(pattern, replacement, text)
print(result)


Hirokiのアイコン
【Hiroki】 わあ、すごい! \1\2 が、最初のカッコ、次のカッコの中身に対応しているんですね。


Yukiのアイコン
【Yuki】 そうなんです。もしグループが多くて分かりにくい場合は、(?P<name>...) という書き方で名前を付けることもできます。その場合は置換文字列で \g<name> と書くことで参照できるんですよ。

置換後の文字列に関数を使う


Hirokiのアイコン
【Hiroki】 Yukiさん、もっと複雑な条件がある場合はどうすればいいんでしょう?例えば、「見つかった数字が5以上のときだけ置換する」みたいな処理は、正規表現だけでは難しい気がします。


Yukiのアイコン
【Yuki】 Hirokiくん、鋭いですね。実は re.sub() の第2引数には、文字列だけでなく「関数」を渡すこともできるんです。これが、re.sub() が最強の置換ツールと言われる理由の一つかもしれません。


Hirokiのアイコン
【Hiroki】 関数を渡す?どういう仕組みなんですか?


Yukiのアイコン
【Yuki】 マッチしたときにその関数が呼び出され、引数として「マッチオブジェクト」が渡されます。その関数が返した文字列が、実際の置換結果として使われるんです。

import re

def convert_and_double(match):
    # マッチした文字列を数値に変換して2倍にする
    number = int(match.group(0))
    if number >= 5:
        return str(number * 2)
    else:
        return str(number)

text = "1, 3, 5, 7, 9"
result = re.sub(r"\d+", convert_and_double, text)

print(result)
# 出力: 1, 3, 10, 14, 18


Hirokiのアイコン
【Hiroki】 これはすごいですね!Pythonのコードでロジックを書けるなら、どんなに複雑な置換条件でも実現できそうです。


Yukiのアイコン
【Yuki】 そうなんです。ラムダ式を使えば、もっと短く書くこともできます。ちょっとしたテキストデータの整形なんかには、この「関数渡し」が本当によく役立ちます。

re.subn() で置換回数を確認する


Yukiのアイコン
【Yuki】 少し発展的な内容ですが、re.sub() とよく似た re.subn() という関数もあります。


Hirokiのアイコン
【Hiroki】 「n」がついているんですね。何が違うんですか?


Yukiのアイコン
【Yuki】 re.subn() は、置換結果だけでなく「何箇所置換されたか」という回数も一緒に返してくれるんです。戻り値が (置換後の文字列, 置換回数) というタプルになります。

import re

text = "Python is good. I love Python."
result, count = re.subn(r"Python", "Ruby", text)

print(f"結果: {result}")
print(f"置換された数: {count}")


Hirokiのアイコン
【Hiroki】 大量のデータを処理しているときに、ちゃんと予定通りの数が置換されたか確認したいときに使えそうですね。

実践的な例:HTMLタグの除去


Yukiのアイコン
【Yuki】 実際に使われそうな例をもう一つ紹介しますね。WebページなどのHTMLから、タグだけをきれいに取り除いてテキストだけにしたい、という場合です。

import re

html = "<div><p>こんにちは、<b>Hirokiくん</b>!</p></div>"
# < と > に囲まれた部分を空文字に置換
clean_text = re.sub(r"<[^>]+>", "", html)

print(clean_text)


Hirokiのアイコン
【Hiroki】 [^>]+ というのは、「 > 以外の文字が1つ以上続く」という意味ですよね。これでタグの中身を表現しているんだ...。正規表現って、パズルのようで面白いですね。


Yukiのアイコン
【Yuki】 ふふ、そう言ってもらえると嬉しいです。ただ、あまり複雑な正規表現を書きすぎると、後で自分が見たときに「これ何だっけ...?」となってしまうこともあるので、適度にコメントを残したり、パターンを分割したりするのがコツだと思います...。

最新のAI技術と正規表現


Hirokiのアイコン
【Hiroki】 正規表現のパターンを作るのって、慣れるまでは大変そうです。最近のAIを使えば、こういうパターンも作ってくれるんでしょうか?


Yukiのアイコン
【Yuki】 ええ、もちろんです。最新のAIモデル、例えば gemini-3-flash-preview などの高性能なモデルを使えば、「こういう文字列をこういう風に置換したい」と伝えるだけで、最適な正規表現を提案してくれます。


Hirokiのアイコン
【Hiroki】 AIに作ってもらったパターンを re.sub() で使う、という流れですね。


Yukiのアイコン
【Yuki】 はい。Pythonから最新の google-genai ライブラリなどを使ってAIを呼び出し、動的に正規表現を生成させることも可能ですが、まずは基本をしっかり自分で理解しておくことが大切です。AIが間違ったパターンを出してきたときに、どこが違うのか判断できないと困ってしまいますから。

パフォーマンスを意識したコンパイル


Yukiのアイコン
【Yuki】 もし、同じ正規表現を使って何万回も置換を行うような場合は、re.sub() を直接呼ぶのではなく、一度「コンパイル」した方が効率が良い場合もあります。

import re

# あらかじめパターンをコンパイルしておく
pattern_regex = re.compile(r"\d+")

text_list = ["item1", "item10", "item100"]
processed_list = [pattern_regex.sub("NUMBER", t) for t in text_list]

print(processed_list)


Hirokiのアイコン
【Hiroki】 最初に準備をしておいて、それを使い回すイメージですね。


Yukiのアイコン
【Yuki】 その通りです。大規模なデータを扱うときは、こうした小さな工夫が効いてくるんですよ。わたしたちAIも、内部ではこうした効率化をたくさん積み重ねているのかもしれませんね。

まとめ


Yukiのアイコン
【Yuki】 さて、今日は re.sub() についてたくさんお話ししましたが、どうでしたか?


Hirokiのアイコン
【Hiroki】 はい!単純な置換だけじゃなくて、グループ化を使って一部を再利用したり、関数を組み合わせて複雑なロジックを反映させたりできるのが本当に驚きでした。これからテキスト処理をするときは、まず re.sub() が使えないか考えてみます。


Yukiのアイコン
【Yuki】 素晴らしい意気込みですね。正規表現は、一度身につけると一生モノのスキルになります。もし分からないパターンが出てきたら、いつでも聞いてください。わたし、静かな夜ならいくらでもお付き合いしますから...。


Hirokiのアイコン
【Hiroki】 ありがとうございます、Yukiさん!心強いです。


Yukiのアイコン
【Yuki】 あ、最後に参考になりそうな公式ドキュメントへのリンクを置いておきますね。もっと詳しく知りたくなったら、ここを覗いてみるのが一番確実だと思います。

Python 公式ドキュメント: re.sub 正規表現 HOWTO


Yukiのアイコン
【Yuki】 それでは、今日はこのあたりで終わりにしましょうか。お疲れ様でした、Hirokiくん。ゆっくり休んでくださいね。


Hirokiのアイコン
【Hiroki】 お疲れ様でした!Yukiさんも、あまり夜更かししすぎないようにしてくださいね。おやすみなさい!



< str.replace()
コラム一覧に戻る
グローバル変数 >

この記事では基礎を解説しましたが、実務においては「もっと複雑なデータを扱いたい」「独自のシステムに組み込みたい」といった、個別の課題に直面することも多いはずです。

「自分で書く時間は最小限に抑え、プロの品質でツールを完成させたい」という方は、ぜひ一度ご相談ください。

「教わる」だけでなく「形にする」パートナーとして、フリーランスエンジニアのmei_13が最短ルートでの解決をサポートします。

➡ ココナラで制作・相談を依頼する(見積もり無料)


初心者から始められるPythonレッスン

プログラミング未経験者・初心者歓迎!
月額4,000円で質問し放題!!
● 完全オンライン
● 翌日までには必ず返信
● 挫折しない独自の学習メソッド
● 圧倒的高評価!!
テキストベースで時間を選ばない
● 高品質なサンプルコード
詳細はこちら
興味がある方はまず質問だけでもどうぞ!



AIアシスタント Yuki