もっと便利な道具

INPUT · スライド

形をたよりに探す

01 / 07

言葉では言い表せない探しもの

第2章で in や find を覚えたね。あれは「この言葉があるか」を調べる道具だった。

でも、探したいものがいつも言葉で言えるとは限らないよ。

  • 「数字がならんでいるところ」
  • 「郵便番号っぽい形をしたところ」
  • 「ひらがなだけが続いているところ」

これは言葉ではなく形だね。形を書き表すための書きかたを 正規表現(せいきひょうげん)と呼ぶよ。

02 / 07

re を読みこんで search する

正規表現は re(アールイー)というモジュールに入っている。第6章でやった import で読みこもう。

いちばんよく使うのが re.search。「その形がどこかにあるか」を探して、見つかった部分を返してくれるよ。

r"\d+" が「形」の部分。\d が数字1文字、+ が1個以上という意味だから、あわせて「数字が1個以上ならんだところ」だね。

import remoji = "でんわは09012345678です"m = re.search(r"\d+", moji)if m:    print(m.group())

実行結果

09012345678

03 / 07

なぜ r を付けるのか

形を書くときは、クォートの前に r を付ける。これは raw(ロウ、生の)という意味だよ。

ふつうの文字列では、\n が「改行1文字」に化けてしまう。バックスラッシュが特別な合図として食べられてしまうんだ。

r を付けると、そういう読みかえをやめて書いたままの2文字として渡してくれる。正規表現はバックスラッシュを山ほど使うので、r を付けるのが決まりだと思っておこう。

print(r"\n")print(len(r"\n"))print(len("\n"))

実行結果

\n
2
1

04 / 07

覚える記号はこれだけ

正規表現には記号がたくさんあるけれど、この章で扱うのは下の9つだけだよ。

記号意味
\d数字1文字
\w文字1文字(英数字・かな・漢字)
.なんでも1文字
+直前が1個以上
*直前が0個以上
{3}直前がちょうど3個
[あ-ん]この範囲のどれか1文字
^先頭
$末尾

全部覚える必要はない。「こういうものがある」と知っていて、必要なときに調べられれば十分だよ。

import reprint(re.findall(r"\d+", "りんご3こ みかん12こ"))print(re.findall(r"[あ-ん]+", "りんご3こ"))

実行結果

['3', '12']
['りんご', 'こ']

05 / 07

見つからないと None

ここがいちばん大事なところ。re.search は見つからなかったとき None を返すよ。

エラーにはならない。静かに None が返ってくるだけだ。第1章でやった「値が無いということ」が、ここで効いてくるんだ。

import rem = re.search(r"\d+", "すうじはありません")print(m)

実行結果

None

06 / 07

確かめてから group を呼ぶ

None に group() は無い。確かめずに呼ぶと落ちるよ。

だから正規表現を使うときは、必ず if m: ではさむ。これがお決まりの形だよ。

m = re.search(r"\d+", moji)if m:    print(m.group())

この3行を指が覚えるまで書こう。見つからないかもしれないものを扱うときの、基本の作法だよ。

import rem = re.search(r"\d+", "すうじはありません")print(m.group())

実行結果

AttributeError: 'NoneType' object has no attribute 'group'

07 / 07

findall で全部、match で先頭から

re.search の仲間があと2つあるよ。

  • re.findall … 当てはまるところを全部集めて、文字のリストで返す。見つからなければ空のリスト
  • re.match … 先頭から当てはまるかだけを見る。途中にあっても見つけてくれない

findall はリストが返るので group() が要らない。いちばん気楽に使えるのはこれだよ。

次のレッスンでは、見つけた部分をさらに分けて取り出す書きかたを覚えよう。

import reprint(re.findall(r"\d+", "a1b22"))m = re.match(r"\d+", "123あ")if m:    print(m.group())print(re.match(r"\d+", "あ123"))

実行結果

['1', '22']
123
None