以下の記事を参考に正規表現についてまとめる
出典:https://docs.python.org/3.13/howto/regex.html
特殊文字とは
通常の文字のようにそれ自身とマッチしない文字であり、合図を出すなどの意味を有する。
. ^ $ * + ? { } [ ] \ | ( )
[]:文字クラス
[]はマッチしたい文字の集合を表す。(\を除く)特殊文字は文字クラスの内部では有効にならない
- [abc]:a, b, cを表す
- [a-c]:同上
^:補集合
クラスの最初の文字に^を指定することで補集合を表すことができる。
- [^5]:5以外の文字を表す
\:文字と合わせて特殊シーケンスを作る
「‘\’+文字」で様々な特殊シーケンスを作成する。
特殊文字の前に置くことで、特殊文字をマッチさせる際にも使われる。
- \w:任意の英数字文字および下線 [a-zA-Z0-9_]
- \W:任意の非英数字文字 [^0-9]
- \d:任意の十進数 [0-9]
繰り返し
*:繰り返し(スター演算)
これまでの特殊文字は一文字に対してマッチさせるものが多かった。*は繰り返しに対応させることができる。計算論でいうスター演算にあたり、ある文字の0個以上の繰り返しのパターンを指定する。
- ca*t:ct, cat, caat, caaat, caaaat….
+:繰り返し(1回以上)
*は繰り返し回数として0回以上であったが、+は繰り返し回数として1回以上。
- ca+t:cat, caat…..
{m, n}:繰り返し(m回以上n回以下)
繰り返しの最小値・最大値を指定できる。
- a/{1, 3}b:a/b, a//b, a///b
正規表現の使用方法
正規表現をパターンオブジェクトにコンパイルしたのちに、マッチを実行する。
re.compileに渡される正規表現はpythonの通常の文字列である。
import re
p = re.compile('ab*')
バックスラッシュ問題
問題
正規表現を記述するにあたってバックスラッシュが大量に発生してしまうという問題が存在するのでそれについて説明する。
「\section」の正規表現を作成してみる
- \section:マッチさせるテキスト
- \section:sectionの前に存在する「\」は特殊文字ではなく通常の文字として扱う必要があるので、エスケープ用に「\」を前方に追加する。
- \\section:pythonの文字列リテラルで\をエスケープさせるために\を各々の\の前に追加する
このように「\\section」と表す必要があり、理解の難しい表現となってしまう。
print('\\') #print('\')はエラー
>> \
解決方法
Pythonのraw string記法を使用する。rを文字列リテラルの先頭に書くことでバックスラッシュが特別扱いされなくなる。
- “\\section” → r”\section”
print('\n') # -> 改行
print(r'\n') # -> \nと出力される
マッチの実行
パターンオブジェクトのメソッドを使用することによってマッチを実行することができる。台上的なものは以下の通り。
- match():文字列の先頭で正規表現とマッチするか判定します。
- search():文字列を先頭から走査して、正規表現がどこにマッチするか調べます。
- findall():正規表現にマッチする部分文字列を全て探しだしリストとして返します。
- finditer():正規表現にマッチする部分文字列を全て探しだし iterator として返します。
match()の使用方法
[a-z]+(アルファベットの小文字のみで構成された1文字以上の文字列)に対するマッチングを試してみる。
import re
p = re.compile('[a-z]+')
m = p.match("") # > None
m = p.match('tempo') # > <re.Match object; span=(0, 5), match='tempo'>
ここでmatch()の返り値はMatchオブジェクトである。
Matchオブジェクトインスタンスの重要なメソッドは以下の通り。
- group():正規表現にマッチした文字列を返す
- start():マッチの開始位置を返す
- end():マッチの終了位置を返す
- span():マッチの位置(start, end)を含むタプルを返す