【re】Pythonで正規表現:reモジュールの基本的な使用方法

概要

Pythonのreモジュールを使用して、正規表現をどのように使用するのかをまとめた。

 

正規表現のパターン

文字列から特定のパターンを探す際に、正規表現を使用する。
パターンは通常の文字や特殊文字、特殊シーケンスを組み合わせて作成する。

 

特殊文字

主な特殊文字のパターンとして以下がある。

特殊文字 説明
. 改行以外の任意の一文字
^ 文字列の先頭
$ 文字列の末尾
* 直前文字の0回以上の繰り返し
+ 直前文字の1回以上の繰り返し
? 直税文字の0回または1回
{n} 直前文字のn回の繰り返し
{m, n} 直前文字のm~n回の繰り返し
\ 特殊文字のエスケープ
[文字の集合] 集合の中の一文字
[^文字の集合] 集合に含まれない1文字
| いずれか
() グループ(キャプチャ)化

 

特殊シーケンス

主な特殊シーケンスとして、以下がある。

 

特殊シーケンス  
\d 任意の数字
\D \d以外
\s 任意の空白文字
\S \s以外
\w 任意のUnicode単語文字
\W \w以外
\A 文字列の先頭(特殊文字「^」と同じ)
\Z 文字列の末尾(特殊文字「$」と同じ)

 

 

reの主な使い方

reモジュールの主な正規表現パターンとしては、match()を使用するケースとsearch()を使用するケースがある。

re.match(“正規表現”, “対象の文字列”)

match関数の場合、正規表現パターンが文字列の先頭にマッチするかどうかを確認する。
つまり、この関数は文字列の最初からパターンマッチングを始めるため、パターンが対象文字列の途中からマッチする場合は検出できない

 

特殊文字

 


import re

# 特殊文字:.(改行以外の任意の一文字)
m1 = re.match("a.c", "abcd") # a+[任意の一文字]+c
print("m1", m1) # m1 <re.Match object; span=(0, 3), match='abc'>
print(m1.group(0)) # abc
m2 = re.match("a.c", "ac abbc")
print("m2", m2) # m2 None

# 特殊文字:^(字列の先頭)
m3 = re.match("^ab", "abc") # 先頭からabで始まる
print("m3", m3) # m3 <re.Match object; span=(0, 2), match='ab'>
print(m3.group(0)) # ab
m4 = re.match("^ab", "cab")
print("m4", m4) # m4 None

# 特殊文字:$(文字列の末尾)
m5 = re.match("ab$", "ab") # aで始まりbで終わる
print("m5", m5) # m5 <re.Match object; span=(0, 2), match='ab'>
print(m5.group(0)) # ab
m6 = re.match("ab$", "cab")
print("m6", m6) # m6 None

# 特殊文字:*(直前の文字の0回以上の繰り返し)
m7 = re.match("ab*", "abbbbbbb bbb")
print("m7", m7) # m7 <re.Match object; span=(0, 8), match='abbbbbbb'>
print(m7.group(0)) # abbbbbbb
m8 = re.match("ab*", "caabbbbbbb bbb")
print("m8", m8) # m8 None

# 特殊文字:+(前の文字の1回以上の繰り返し)
m9 = re.match("ab+", "abbbbbbb bbb")
print("m9", m9) # m9 <re.Match object; span=(0, 8), match='abbbbbbb'>
print(m9.group(0)) # abbbbbbb
m10 = re.match("ab+", "aabbbb")
print("m10", m10) # m10 None

# 特殊文字:?(直前の文字の0回または1回)
m11 = re.match("ab?", "acdde")
print("m11", m11) # m11 <re.Match object; span=(0, 1), match='a'>
print(m11.group(0)) # a
m12 = re.match("ab?", "bab b")
print("m12", m12) # m12 None

# 特殊文字:{m} (直前の文字のm回の繰り返し)
m13 = re.match("a{2}", "aa ab")
print("m13", m13) # m13 <re.Match object; span=(0, 2), match='aa'>
print(m13.group(0)) # aa
m14 = re.match("a{2}", "a aa b")
print("m14", m14) # m14 None

# 特殊文字:{m,n}(直前の文字のm回からn回の繰り返し)
m15 = re.match("a{2,3}", "aaaabc")
print("m15", m15) # m15 <re.Match object; span=(0, 3), match='aaa'>
print(m15.group(0)) # aaa
m16 = re.match("a{2,3}", "abaaabc")
print("m16", m16) # m16 None

# 特殊文字:{m} の組み合わせ
m17 = re.match("88(7{2})?", "88")
print("m17", m17) # m17 <re.Match object; span=(0, 2), match='88'>
m18 = re.match("88(7{2})?", "8877")
print("m18", m18) # m18 <re.Match object; span=(0, 4), match='8877'>

re.match()にてマッチした場合、matchオブジェクトが返却される。
「返却されたmatchオブジェクト.group(0)」と記述すると、マッチした文字列を取得可能。

 

特殊シーケンス

 


import re

# 任意の数字1回以上の繰り返し
print(bool(re.match(r"\d+$", "123"))) # True
print(bool(re.match(r"\d+$", "123a"))) # False
# 任意の空白文字1回以上の繰り返し
print(bool(re.match(r"\s+$", "\t \n"))) # True
print(bool(re.match(r"\s+$", "\t \na"))) # False
# 任意の文字の繰り返し
print(bool(re.match(r"\w+$", "あい12ab"))) # True
print(bool(re.match(r"\w+$", "あい12ab "))) # False
# 文字との組み合わせ
print(bool(re.match(r"Py\s?thon$", "Python"))) # True
print(bool(re.match(r"Py\s?thon$", "Py thon"))) # True
print(bool(re.match(r"Py\s?thon$", "Py  thon"))) # False
print(bool(re.match(r"Py\s+thon", "Python"))) # False
print(bool(re.match(r"Py\s+thon", "Py thon"))) # True
print(bool(re.match(r"Py\s+thon", "Py  thon"))) # True

 

re.matchの結果をboolでラップすると真偽値を取得可能。
「r”正規表現”」という書き方はraw文字列と呼ばれエスケープシーケンスを無視できる


import re 

# 特殊文字:\(特殊文字のエスケープ) 
m1 = re.match("\.ac", ".acb") 
print("m1", m1) # m1  

m2 = re.match(r".ac", ".acb") 
print("m2", m2) # m2 

 

集合文字

 


import re

# a~zまでの文字が1回以上の繰り返し
print(bool(re.match("[a-z]+", "python")))  # True
# a~z、0~9までの文字が1回以上の繰り返し
print(bool(re.match("[a-z0-9]+", "007bond")))  # True
# a~z、0~9まで、アンダースコア(_)の文字が1回以上の繰り返し
print(bool(re.match("[a-z0-9_]+", "007_bond")))  # True
# a~z、0~9まで、アンダースコア(_)の文字以外が1回以上の繰り返し
print(bool(re.match("[^a-z0-9_]+", "BOND")))  # True

 

(OR)条件

「|」を使用してOR条件を作成する際には、括弧()でくくってグループ化しないと正しく動作しない。


import re

# 「ab」または「cd」または「数字が1回以上」
pattern = r"(ab|cd|\d+)$"

print(bool(re.match(pattern, "ab")))  # True
print(bool(re.match(pattern, "abc")))  # False
print(bool(re.match(pattern, "cde")))  # False
print(bool(re.match(pattern, "123")))  # True
print(bool(re.match(pattern, "ab123")))  # False
print(bool(re.match(pattern, "cd")))  # True

 

if条件で使用する方法

match()の条件にマッチしない場合はNoneが返却され、マッチした場合はmatchオブジェクトが返却される。
matchの結果をif文で記述するには、その結果を条件にそのまま指定すればOK。


import re

m1 = re.match("^\w{2}$", "ab123")
if m1:
    print("マッチ")
else:
    print("マッチしない")

m2 = re.match(r"\w+$", "cd")
if m2:
    print("マッチ")
else:
    print("マッチしない") 
# ----------------------------------------
# 出力
#マッチしない
#マッチ

 

注意点

matchを使用して文字全体に対してマッチングを行う場合、「$」をパターンにつけること。
そうしないと意図しないパターンをマッチングさせてしまう。


import re

posts = [
    "004-0055",
    "0293207",
    "039-237212",
    "51-0001"
    "072-0000-1"
]

# 郵便番号7桁判定(ハイフン有でも無でも)
for post in posts:
    if re.match(r"\d{3}-?\d{4}", post):
        print(post)
# -------------------------------------------
# 出力
#004-0055
#0293207
#039-237212

上記は郵便番号7桁(ハイフンは問わない)をマッチングさせようとした結果、意図しない郵便番号までマッチングしたケース。
※文字列の先頭から正規表現のパターンにマッチしたものを抽出するため

 

郵便番号7桁(ハイフンは問わない)を正しくマッチングさせるためには以下のように「$」を記述する。


import re

posts = [
    "004-0055",
    "0293207",
    "039-237212",
    "51-0001"
    "072-0000-1"
]

# 郵便番号7桁判定(ハイフン有でも無でも)
for post in posts:
    if re.match(r"\d{3}-?\d{4}$", post):
        print(post)
# -------------------------------------------
# 出力
#004-0055
#0293207

 

re.search(“正規表現”, “対象の文字列”)

search関数の場合、正規表現パターンが文字列のどこかにマッチするかどうかを確認する。
つまり、この関数は文字列全体を検索し、パターンがマッチする最初の位置を見つける。

特殊文字

 


import re 

# 特殊文字:.(改行以外の任意の一文字) 
m1 = re.search("a.c", "dabce") # 先頭からa+[任意の一文字]+c 
print("m1", m1) # m1 <re.Match object; span=(1, 4), match='abc'> 
print(m1.group(0)) # abc 
# 特殊文字:^(字列の先頭) 
m2 = re.search("^ab", "abc") # 先頭からabで始まる 
print("m2", m2) # m2 <re.Match object; span=(0, 2), match='ab'> 
print(m2.group(0)) # ab 
# 特殊文字:$(文字列の末尾) 
m3 = re.search("ab$", "aaxzab") # abで終わる 
print("m3", m3) # m3 <re.Match object; span=(4, 6), match='ab'> 
print(m3.group(0)) # ab 
# 特殊文字:*(直前の文字の0回以上の繰り返し) 
m4 = re.search("ab*", "ccccabbbbbbb bbb") # a+(bの0回以上の繰り返し)
print("m4", m4) # m4 <re.Match object; span=(4, 12), match='abbbbbbb'> 
print(m4.group(0)) # abbbbbbb 
# 特殊文字:+(前の文字の1回以上の繰り返し) 
m5 = re.search("ab+", "cdabbbbb bbb") # a+(bの1回以上の繰り返し)
print("m5", m5) # m5 <re.Match object; span=(2, 8), match='abbbbb'> 
print(m5.group(0)) # abbbbb 
# 特殊文字:?(直前の文字の0回または1回) 
m6 = re.search("ab?", "zdacdde") # a+(bの0回または1回の繰り返し)
print("m6", m6) # m6 <re.Match object; span=(2, 3), match='a'> 
print(m6.group(0)) # a 
# 特殊文字:{m} (直前の文字のm回の繰り返し) 
m7 = re.search("a{2}", "ccaa ab") # aの2回繰り返し
print("m7", m7) # m7 <re.Match object; span=(2, 4), match='aa'> 
print(m7.group(0)) # aa 
# 特殊文字:{m,n}(直前の文字のm回からn回の繰り返し) 
m8 = re.search("a{2,3}", "caaabc") # aの2回以上3回以下の繰り返し
print("m8", m8) # m8 <re.Match object; span=(1, 4), match='aaa'> 
print(m8.group(0)) # aaa

 

グループ化

括弧()でくくると、その対象となる文字列を抽出できる。
※or条件の括弧()と混同しないこと


import re

sentence = 'The only impossible journey is the one you never begin.(Tony Robbins)'

m = re.search('((.*))', sentence) # 大括弧()で囲まれた部分
print(m.group(0)) # (Tony Robbins)
print(m.group(1)) # Tony Robbins

address = "山田君の住所:100-0000東京都千代田区"
m2 = re.search("(\d{3}-\d{4})(\w+(県|都|道))", address)
print(m2.group(0)) # 100-0000東京都
print(m2.group(1)) # 100-0000
print(m2.group(2)) # 東京都

 

matchオブジェクト.group(0):マッチした全体を取得
matchオブジェクト.group(1以降):マッチしたグループ内を取得

 

reモジュールのその他関数

関数 詳細
match 先頭からマッチするか
search 途中でマッチするか
split 区切り文字をパターンで指定して分割
sub パターンを別の文字に置換

findall

全てのパターンを列挙してリスト化

 


import re 

print(re.split("[:;/]", "a:b;c/d")) # ['a', 'b', 'c', 'd'] 
print(re.sub(r"{}", "田中", "こんにちは、{}さん")) # こんにちは、田中さん 
print(re.findall(r'\d+', '代金1,980円')) # ['1', '980']
スポンサーリンク