Pythonで正規表現を文字列操作を行う方法を紹介します。
正規表現で文字列を操作するといっても、
検索・置換・連結・分割などやりたいことは様々あります。
またこの記事ではPythonの正規表現でハマる「複数行」の扱い方についても紹介しております。
正規表現操作を行う標準ライブラリ「re」
正規表現のマッチング操作を行うのはPython標準ライブラリの「re」を使います。
使用出来る正規表現の特殊文字(シンタックス)は、Perlなどと同様の特殊文字が実装されています。
また正規表現の指定方法は2つあり、「通常モード」と「row string記法モード」があります。
通常モードは以下のように使用します
re.search('abcd', 'abcdefghijklnm')
row string記法モードは、以下のように先頭に「r」を使用します。
re.search(r'abcd', 'abcdefghijklnm')
通常モードとrow string記法モードの違いは、「\(バックスラッシュ)」の扱い方になります。
例えば通常モードで「\n」そのものをマッチさせるためには「\\n」と記載しなければいけません。
row string記法モードで「\」そのものをマッチさせるためには「\」と記載します。
以下、バックスラッシュの使用例になります。
>>> print(re.findall("\\newfolder", "Programfolder\newfolder"))
['\newfolder']
>>>
>>> print(re.findall(r"\newfolder", "Programfolder\newfolder"))
['\newfolder']
>>>
※さらに通常モードで「\」そのものをマッチさせるためには「\\\\」と記載しなければいけません。
詳細についてPython公式マニュアルを参照ください。
search():文字列がマッチするか調べる
「search()」文字列がマッチするかどうかを調べます。
>>> print(re.search("[0-9]{3}", "123-4567 This is test."))
<_sre.SRE_Match object; span=(0, 3), match='123'>
match():文字列の先頭がマッチするか調べる
「match()」は文字列の先頭がマッチするかどうかを調べます。
>>> print(re.match("[0-9]{3}", "123-4567 This is test."))
<_sre.SRE_Match object; span=(0, 3), match='123'>
>>> print(re.match("[0-9]{4}", "123-4567 This is test."))
None
2行目では先頭がマッチしていないため、「None」が返却されます。
findall():マッチする文字列のリストを作成
「findall()」はマッチした文字列のリストを作成します。
import re
re.findall(<正規表現>, <文字列>)
下が実行サンプルです。
>>> print(re.findall("[0-9]{3}", "123-4567 This is test."))
['123', '456']
「This」の「is」と「is」がマッチしているためリストとして返ってきています。
finditer():マッチする文字列のイテレーターを作成
「finditer()」はマッチした文字列のイテレーターを作成します。
import re
re.finditer(<正規表現>, <文字列>)
下が実行サンプルです。
>>> print(re.finditer("[0-9]{3}", "123-4567 This is test."))
<callable_iterator object at 0x000002F57E876208>
>>> for value in re.finditer("[0-9]{3}", "123-4567 This is test."):
... print(value)
...
<_sre.SRE_Match object; span=(0, 3), match='123'>
<_sre.SRE_Match object; span=(4, 7), match='456'>
sub()、subn():マッチした文字列を置換
「sub()」、「subn()」はマッチした文字列を置換します。
「subn()」は置換させた文字列の個数も合わせて返してくれます。
import re
re.sub(<正規表現>, <置換させたい文字列>, <文字列>)
または、
import re
re.subn(<正規表現>, <置換させたい文字列>, <文字列>)
下が実行サンプルです。
>>> print(re.sub("[0-9]{3}", "***", "123-4567 This is test."))
***-***7 This is test.
>>> print(re.subn("[0-9]{3}", "***", "123-4567 This is test."))
('***-***7 This is test.', 2)
split:マッチした文字列を分割
「split()」はマッチした文字列を分割します。
import re
re.split(<正規表現>, <文字列>)
下が実行サンプルです。
>>> print(re.split("[0-9]{3}", "123-4567 This is test."))
['', '-', '7 This is test.']
compile:正規表現オブジェクトをコンパイル
「compile()」は正規表現のオブジェクトをコンパイルします。
同じパターンの正規表現を使用する場合にオブジェクトを作成しておくと便利です。
import re
re.compile(<正規表現>)
下が実行サンプルです。
>>> string = re.compile("[0-9]{3}")
>>> print(string.sub("***","123-4567 This is test."))
***-***7 This is test.
複数行マッチさせる方法
正規表現で複数行を操作するためには特殊なフラグを使用する必要があります。
また複数行と言っても、
- 先頭パターン文字\’^\’と末尾パターン文字\’$\’を使用して1行ごとに正規表現でマッチさせる
- 複数行にわたる文字列を正規表現でマッチさせる
の2つのパターンがあります。
指定方法は以下になります。
flags=re.MULTILINE # '^'と'
#039;を使用し1行ごとにマッチさせる
flags=re.DOTALL
# 複数行にまたいでマッチさせる
flags=(re.MULTILINE | re.DOTALL) # 両方指定
re.MULTILINE:先頭パターン文字\’^\’と末尾パターン文字\’$\’を使用して1行ごとにマッチさせる
先頭パターン文字\’^\’と末尾パターン文字\’$\’を使用して1行ごとにマッチさせるには、
「flags=(re.MULTILINE)」を使用します。
上記で説明しました「search」、「findall」、「sub」などですべての「re」ライブラリで使用出来います。
先頭パターン文字\’^\’を使用して1行ごとにマッチさせる例を紹介します。
>>> string = """\
... 123-4567 XXXXXXXXX
... 890-1234 YYYYYYYYY
... 567-8901 ZZZZZZZZZ
... """
>>> print(re.sub('^[0-9]{3}-[0-9]{4}', '***-****', string))
***-**** XXXXXXXXX
890-1234 YYYYYYYYY
567-8901 ZZZZZZZZZ
>>> print(re.sub('^[0-9]{3}-[0-9]{4}', '***-****', string, flags=re.MULTILINE))
***-**** XXXXXXXXX
***-**** YYYYYYYYY
***-**** ZZZZZZZZZ
re.DOTALL:複数行にわたる文字列でマッチさせる
複数行にわたる文字列をマッチさせるには、「re.DOTALL」を指定します。
これは改行を含むすべての文字を特殊文字\’.\’をマッチさせるという意味になります。
上記で説明しました「search」、「findall」、「sub」などですべての「re」ライブラリで使用出来います。
複数行にわたる文字列をマッチさせる例を紹介します。
>>> string = """\
... /*
... これはコメントです。
... これはコメントです。
... これはコメントです。
... */
... This is test.
... """
>>> print(re.sub('\/\*.*\*\/', '', string))
/*
これはコメントです。
これはコメントです。
これはコメントです。
*/
This is test.
>>> print(re.sub('\/\*.*\*\/', '', string, flags=re.DOTALL))
This is test.