メタ文字③ 繰り返しパターン/任意の文字列

メタ文字③ 繰り返しパターン/任意の文字列

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

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

1回以上の繰返し

 + は直前の文字の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の検索結果 ['ああ']

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

# 正規表現オブジェクトを作成
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文字以上の後ろの添えるのが一般的です。たとえば、おい!* という正規表現の場合、* の直前にある文字は ! ですから、

  ・おい
  ・おい!!
  ・おい!!!

のような文字列にマッチすることになります。つまり、! はあってもなくてもいい、という条件で検索します。

# reモジュールをインポート
import re

# 正規表現オブジェクトを作成
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 回以下の文字列にマッチします。つまり、

 ・わはははは

のような文字列にはマッチしますが、

 ・わはは

にはマッチしません。

# 正規表現オブジェクトを作成
regex = re.compile(r'わは{3,5}')

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

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

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

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

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

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

# reモジュールをインポート
import re

# 正規表現オブジェクトを作成
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 文字を表すメタ文字になります。

# 正規表現オブジェクトを作成
# フラグに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