繰り返しパターンと任意の文字列

繰り返しパターンと任意の文字列

文字列の繰返しにマッチする正規表現

 +* などのメタ文字を使うと、文字列の繰返しにマッチする正規表現 をつくることができます。

1回以上の繰返し

 + は直前の文字の1回以上の繰返しを意味するメタ文字です。
 たとえば、は+
 
 ・ははは
 ・はははは
 ・あははは
 
などの文字列にマッチします。

# PYTHON_REGEX_REPEAT_MATCH

# In[1]

# 正規表現オブジェクトを作成
regex = re.compile(r'あ+')

# 検索対象となる文字列を作成
line_1 = "あ~あ。牛乳をこぼしちゃった。"

line_2 = "ああっ! しまった! 宿題を忘れた!"

# line_1を検索
f1 = regex.findall(line_1)

# line_2を検索
f2 = regex.findall(line_2)

print("line1の検索結果", f1)
print("line2の検索結果", f2)

# line1の検索結果 ['あ', 'あ']
# line1の検索結果 ['ああ']

 ( ) で括った文字列の後ろに+ を付けると、( ) の中の文字列が繰り返されるパターンとマッチするようになります。

# In[2]

regex = re.compile(r'(くた)+')

# 検索対象となる文字列を作成
line = "Pythonやり過ぎてくたくたに疲れた。"

# lineを検索
s = regex.search(line)

print("lineの検索結果", s)
# <_sre.SRE_Match object; span=(11, 15), match='くたくた'>

0 回以上の繰返し

 * は直前の文字の 0 回以上の繰返しを意味するメタ文字です。お*
 
 ・おっす!
 ・おおっと!
 ・おいおい。
 
などの文字列にマッチしますが、abcdeあいうえお など、他のどんな文字列ともマッチしてしまいます。
 
 したがって、* は2文字以上の後ろの添えるのが一般的です。たとえば、おい!* という正規表現の場合、* の直前にある文字は ! ですから、
 
 ・おい
 ・おい!!
 ・おい!!!
 
のような文字列にマッチすることになります。つまり、! はあってもなくてもいい、という条件で検索します。

# In[3]

regex = re.compile(r'おい!*')

# 検索対象となる文字列を作成
line_1 = "このお菓子は、とてもおいしいですね。"

line_2 = "おい!! 何やってるんだよ!!"

line_3 = "おいおい。そりゃないだろ。"

# line_1を検索
f1 = regex.findall(line_1)

# line_2を検索
f2 = regex.findall(line_2)

# line_3を検索
f3 = regex.findall(line_3)

print("line1の検索結果", f1)
print("line2の検索結果", f2)
print("line3の検索結果", f3)

# line1の検索結果 ['おい']
# line2の検索結果 ['おい!!']
# line3の検索結果 ['おい', 'おい']

繰り返し回数の指定

 {m,n} は直前の文字の m 回以上、n 回以下の繰り返しを表すメタ文字です。たとえば、わは{3,5} が 3 回以上、5 回以下の文字列にマッチします。つまり、
 
 ・わはははは
 
のような文字列にはマッチしますが、
 
 ・わはは
 
にはマッチしません。

# In[4]

regex = re.compile(r'わは{3,5}')

# 検索対象となる文字列を作成
line = "わはは。わはははは。"

# sentenceを検索して適合した文字列をすべて取得
f = regex.findall(line)

print(f)
# ['わはははは']

 n を省略して {m,} のように書くこともできます。{0,}* と、{1,}+ と同じ意味をもちます。
 

あらゆる文字列にマッチする正規表現

 .* は「改行以外の任意の 1 文字の 0 回以上の繰返し」なので、改行を除くあらゆる文字列にマッチするメタ文字 です。このような正規表現は、たとえば「住所:」や「氏名:」などの後に続く文字列を取り出したいときなどに使います。

# In[5]

regex = re.compile('住所:(.*)')

# 住所
line = '住所:東京都豊島区南池袋 x-y-z あとりえこばと出版'

# グループ1に適合する文字列を取得
g1 = regex.search(line).group(1)

print(g1)
# 東京都豊島区南池袋 x-y-z あとりえこばと出版

 re.compile() のフラグに re.S または re.DOTALL を指定すると、. は改行を含む任意の 1 文字を表すメタ文字になります。

# In[6]

# 正規表現オブジェクトを作成
# フラグにre.Sを渡して改行を含むように設定
regex = re.compile('氏名:(.*)\n住所:(.*)', re.S)

# 検索対象文字列
my_data = '氏名:城戸涼音\n\
住所:東京都文京区小石川 x-y-z'

# my_dataを検索
s = regex.search(my_data)

# グループ1に適合する文字列を取得
g1 = s.group(1)

# グループ2に適合する文字列を取得
g2 = s.group(2)

print(g1)
print(g2)

# 城戸涼音
# 東京都文京区小石川 x-y-z