TL;DR
正規表現はテキストの一部にマッチさせることのできるパターンである。メタ文字と呼ばれる記号を利用し、文字列の検索パターンを表すことができる。任意の文字列の中からパターンに合致する文字列を抽出したり置換を行う。Python では正規表現機能は、標準ライブラリの re モジュールによって提供されているのでインポートして使う。
正規表現の意味とマッチ例
汎用的な正規表現は次のようなものがある。
| パターン | 意味 | 使用例 | マッチ |
| -------- | ------------------------------- | ---------------- | ----------------------- | -------------- | -------------- |
| .
| 改行を除く全ての 1 文字にマッチ | .ython | python, Python |
| ^
| 文字列の先頭 | ^... | 行の先頭から 3 文字まで |
| $
| 文字列の末尾 | ...$ | 末尾までの 3 文字 |
| *
| 直前の正規表現が 0 以上繰り返し | p*ython | ython で終わる全て |
| +
| 直前の正規表現が 1 以上繰り返し | p+ython | python |
| ?
| 直前の正規表現が 0 回、or 1 回 | Py?thon | Python, CPython |
| |
| いずれかの文字列 | Python | python | Python, python |
| ()
| グルーピング | (Py | py)thon | Python, python |
| []
| 括弧内の一文字 | [yponthP] | Python, CPython, python |
| {}
| 括弧内に繰り返し数 | p{2} | ppython |
特殊文字
パターン | マッチ |
---|---|
\d | 1 個の数字 |
\D | 1 個の数字以外 |
\w | 1 個の英単語 |
\W | 1 個の英単語以外 |
\s | 1 個の空白文字 |
\S | 1 個の空白文字以外 |
\b | 単語の境界 |
\B | 単語の境界以外 |
文字セット
文字セットを使うと対象を制限することができる。範囲を指定するときは-
、否定を指定するときは ^
を使う。
パターン | 意味 | マッチ |
---|---|---|
python(?=Love) | Love が続いている python | pythonLove |
python(?!Love) | Love が続いていない python | Lovepython |
[a-z] | 小文字の半角英文字 | abcdef ghi jklmn |
[A-Z] | 大文字の半角英文字 | aBcdefG hiJk |
[0-9] | 半角数字を含む | 0120 - 123 の 4567 |
[^0-9] | 半角数字以外を含む | 0123 の 123 |
[a-zA-Z0-9] | 半角小文字大文字数字 | abcABC012 123 |
[ぁ-ん] | ひらがな | あいうえお |
[ァ-ヴ] | カタカナ | カキクケコ |
<.*?> | html タグ | |
^https?://([\w-]+.)+[\w-]+(/[\w-./?%&=]*)?$ | url | https://~ |
例えば「.」は、改行を除くすべての一文字にマッチするので、.ython
とした場合、python, Python, CPython にマッチする。
「猫は哺乳類である。」というテキストにマッチさせたい場合は、は.*である。
というように組み合わせて使う。
正規表現の基礎をおさらいしたところで、Python の 正規表現機能について解説する。
re モジュール
Python においての正規表現機能は re モジュールによって提供されている。
match()はソースの先頭がパターンにマッチするか調べ、seach() は任意の位置でパターンを探す。
関数一覧
関数 | 関数の説明 |
---|---|
match | 先頭がパターンにマッチするか調べる |
search | 任意の位置でパターンを調べる。最初のマッチを返す |
split | パターンの出現で区切ってリストを返す |
findall | 全てのパターンのリストを返す |
sub | パターンを置換して返す |
compile | 正規表現の文字列からパターンオブジェクトを作る |
escape | すべての正規表現用特殊文字をエスケープする |
match() による文字列の先頭のマッチ
.*
は任意の個数の任意の文字という意味。次のコードでは、match() により .*Man
にマッチした文字列 'Young Man' が返されている。
import re
result = re.match(r'.*Man', 'Young Man')
if result:
print(result.group())
# Young Man
sub() による置換
sub()を使って置換することができる。次のコードでは、空白を _
に置き換えている。
import re
text = 'There is always light behind the clouds.'
rep = re.sub(r'\s', '_', text)
print(rep)
# There_is_always_light_behind_the_clouds.
split() による分割
次のコードでは、数字・アルファベット以外の文字で分割し、リストに格納している。
import re
text = 'Once you stop learning, you start-dying.'
rep = re.split(r'[^a-zA-Z0-9]+', text)
print(rep)
# ['Once', 'you', 'stop', 'learning', 'you', 'start', 'dying', '']
findall() を使ってすべてのマッチを検索
findall()は与えられたパターンに一致したすべての部分のリストを返す。次に示すコードは、文字の中に b という一文字の文字列が何個存在するのか調べるものである。
import re
text = 'If you want to be happy, be.'
result = re.findall(r'b', text)
print(len(result))
# 2
次に示すコードは、文字列中の全ての単語をリストに格納している。
import re
text = 'Once you stop learning, you start-dying.'
find = re.findall(r'[a-zA-Z]+', text)
print(find)
# ['Once', 'you', 'stop', 'learning', 'you', 'start', 'dying']
escape()を使ってエスケープする
escape() は、正規表現の演算子として解釈される全ての文字をエスケープする。
import re
text = 'docs.python.org/ja/3/library/functions.html#bool'
esc = re.escape(text)
print(esc)
# docs\.python\.org/ja/3/library/functions\.html\#bool