もっと便利な道具

INPUT · スライド

パターンで置きかえる

01 / 07

replace ではできないこと

第2章で replace を覚えたね。moji.replace("03", "06") のように、決まった文字を別の文字に変える道具だった。

でも「数字を全部 * に変えたい」はどうだろう。数字は 0 から 9 まであるし、桁数もばらばらだ。replace を10回書く? それでも桁はまとめられないね。

形を指定して置きかえたい。そこで出てくるのが re.sub だよ。

moji = "でんわ 03-1234-5678"print(moji.replace("03", "06"))

実行結果

でんわ 06-1234-5678

02 / 07

re.sub の形

re.sub(形, 置きかえる文字, もとの文字列) の3つを渡すよ。順番は「何を・何に・どこで」だね。

当てはまったところが全部置きかわる。replace と同じで、もとの文字列は変わらない(新しい文字列が返る)よ。

import reprint(re.sub(r"\d", "*", "でんわ 03-1234"))

実行結果

でんわ **-****

03 / 07

かたまりごと置きかえる

\d を \d+ に変えると、数字のかたまりが1つとして置きかわるよ。桁がいくつあっても記号1個になる。

\d だと桁数ぶん * が並んで「何桁か」が見えてしまう。どこまでを1つとみなすかを選べるのが re.sub のおもしろいところだね。

import reprint(re.sub(r"\d+", "○", "りんご3こ みかん12こ"))

実行結果

りんご○こ みかん○こ

04 / 07

取り出したものを置きかえ先で使う

( ) で囲んだところは、置きかえる文字の側で \1 \2 として使えるよ。前のレッスンの group(1) group(2) と同じ番号だね。

置きかえる文字のほうにも r を付けるのを忘れずに。バックスラッシュを書いたまま渡したいのは、こちら側でも同じだよ。

import reprint(re.sub(r"(\d+)-(\d+)", r"\2-\1", "03-1234"))

実行結果

1234-03

05 / 07

re.split で分ける

第2章の split は、区切り文字を1つだけしか指定できなかった。"あ,い う" のようにカンマと空白が混ざっていると困るね。

re.split なら区切りを形で書ける。[, ] と書けば「カンマか空白のどちらか」だよ。

import reprint("あ,い う".split(","))print(re.split(r"[, ]", "あ,い う"))

実行結果

['あ', 'い う']
['あ', 'い', 'う']

06 / 07

区切りが続いても大丈夫

区切りが2つ続くと、re.split はあいだに空の文字を作ってしまう。"あ、 い" を [、 ] で分けると、空っぽの要素が1つ混ざるんだ。

これを防ぐのが +。[、, ]+ と書けば「区切りが1個以上続くかたまり」を1つの区切りとして扱えるよ。迷ったら + を付けると覚えておこう。

import reprint(re.split(r"[、, ]", "りんご、 みかん,ぶどう"))print(re.split(r"[、, ]+", "りんご、 みかん,ぶどう"))

実行結果

['りんご', '', 'みかん', 'ぶどう']
['りんご', 'みかん', 'ぶどう']

07 / 07

このグループのまとめ

正規表現でできることを整理しよう。

  • re.search … その形があるか。見つからなければ None
  • re.findall … 当てはまるところを全部集める
  • re.sub … 形を指定して置きかえる
  • re.split … 形を指定して分ける

どれも「決まった文字」ではなく「形」で指定できるのが共通点だね。

記号を全部覚える必要はないよ。\d と + と ( ) が読めれば、たいていのコードは読める。あとは必要になったときに調べれば十分だよ。