これまで、独習Pythonの内容を参考にチートシートを作成してきました。
今回の正規表現に関するチートシートで一区切りとし、次回からは「Pythonではじめるアルゴリズム入門」、"ML for beginners"の内容の学習記録を再利用性・汎用性の高い情報として纏めてみたいと思います。学習予定・記事を執筆予定の書籍・学習コースは以下の通りです。
正規表現の基礎(compile, search)
正規表現を用いれば文字列や数値型のパターンを定義し、またその中からパターンに合うものを検索できます。電話番号・郵便番号などのデータが正しく入力されているかをチェックし、その情報を抽出したい時に使える機能です。
compileで正規表現を定義、searchで正規表現にマッチした文字列の抽出を行います。
import re
msg ="電話番号は、080-111-9999です。"
ptn = re.compile(r"(\d{2,4})-(\d{2,4})-(\d{4})")
if result := ptn.search(msg):
#group(0) - マッチした文字列全体
print(result.group(0))
#group1移行は、マッチした文字列の部分をそれぞれ表示する
print(result.group(1))
print(result.group(2))
print(result.group(3))
else:
#msgにマッチする文字列が何もない場合は、何も表示しない
print("Search did't found the result.")
080-111-9999
080
111
9999
正規表現にマッチした全ての文字を検索(findall, finditer)
findall、finditerを使って、正規表現にマッチした全ての文字列の抽出を行う
msg ="電話番号は、080-111-9999です。携帯は、334-114-1415です。"
ptn = re.compile(r"(\d{2,4})-(\d{2,4})-(\d{4})")
#引っかかった文字列を全て抽出
results = ptn.findall(msg)
for result in results:
print(result)
#引っかかった文字列を全て抽出(Matchオブジェクトとして取得)
results_02 = ptn.finditer(msg)
for result in results_02:
print(result.group())
('080', '111', '9999')
('334', '114', '1415')
080-111-9999
334-114-1415
Matchオブジェクトを使えば、正規表現に合致したデータに関してより詳細なデータを得ることができます。
例えば電話番号の文字が開始・終了するインデックス、市外局番・市内局番・加入者番号等々の情報を抽出したい時に便利です。
msg ="電話番号は、080-111-9999です。携帯は、334-114-1415です。"
ptn = re.compile(r"(\d{2,4})-(\d{2,4})-(\d{4})")
#引っかかった文字列を全て抽出(Matchオブジェクトとして取得)
results_02 = ptn.finditer(msg)
for result in results_02:
print(f"開始インデックス:{result.start()}")
print(f"末尾インデックス:{result.end()}")
print(f"マッチした文字列、全体:{result.group()}")
print(f"マッチした文字列、市外局番:{result.group(1)}")
print(f"マッチした文字列、市内局番:{result.group(2)}")
print(f"マッチした文字列、加入者番号:{result.group(3)}")
開始インデックス:6
末尾インデックス:18
マッチした文字列、全体:080-111-9999
マッチした文字列、市外局番:080
マッチした文字列、市内局番:111
マッチした文字列、加入者番号:9999
開始インデックス:25
末尾インデックス:37
マッチした文字列、全体:334-114-1415
マッチした文字列、市外局番:334
マッチした文字列、市内局番:114
マッチした文字列、加入者番号:1415
マッチフラグの使い方(re.IGNORECASE)
compileメソッドでは、マッチフラグというマッチング時の挙動を指定できます。例えば、メールアドレス等大文字・小文字を区別せずマッチングしたいデータの場合はre.IGNORECASEを使います。
msg ="仕事のメールアドレスはpython@learning.comです。プライベート用はKNPliv@personal.comです。"
ptn = re.compile(r"[ a-z 0-9.!#$%&\'*+/=?^_{|}~-]+@[ a-z 0-9-]+(\.[a-z 0-9-]+)*", re.IGNORECASE)
#引っかかった文字列を全て抽出(Matchオブジェクトとして取得)
results = ptn.finditer(msg)
for result in results:
print(f"開始インデックス:{result.start()}")
print(f"末尾インデックス:{result.end()}")
print(f"マッチした文字列、全体:{result.group()}")
開始インデックス:11
末尾インデックス:30
マッチした文字列、全体:python@learning.com
開始インデックス:41
末尾インデックス:60
マッチした文字列、全体:KNPliv@personal.com
正規表現で文字列を置換(sub)
subメソッドを利用すれば、正規表現にマッチした文字列を置換することができます。
例えば、ハイパーリンクにHTMLのアンカータグを追加したい時に使えます。
msg ="サポートサイトのリンクは、https://www.python.orgです。"
ptn = re.compile(r"http(s)?:///([\w-]*\.)+[\w-]+(/[\w./?%&=-]*)?", re.IGNORECASE)
#文字列を置換
result = ptn.sub( r"<a href ='\g<0>'>\g<0></a>", msg)
print(result)
サポートサイトのリンクは、<a href ='https://www.python.org'>https://www.python.org</a>です。
固定文字列を置き換えるなら、str型のreplaceメソッドでも十分です。
text ="パイソンを使った文字列データです。"
print(text. replace("パイソン", "python"))
pythonを使った文字列データです。
正規表現で文字列を分割(split)
#文字列を数値型で分割する
msg = "にわに3わうらにわに51わにわとりがいる"
ptn = re.compile(r'\d{1,}わ')
result = ptn.split(msg)
print(result)
['にわに', 'うらにわに', 'にわとりがいる']