note.nkmk.me

Pythonの正規表現モジュールreの関数match、search、sub

Date: 2017-09-05 / tags: Python, 文字列操作, 正規表現

Pythonには正規表現の操作を提供するモジュールreが用意されている。

ここでは、正規表現の複雑なパターンは使わず、以下のreモジュールの関数およびコンパイル済み正規表現のメソッドの振る舞いを説明する。

  • 文字列の先頭がパターンにマッチするかを調べるmatch()
  • 先頭に限らずパターンにマッチするかを調べるsearch()
  • マッチする部分すべてをリストで返すfindall()
  • マッチする部分すべてをイテレータで返すfinditer()
  • マッチした部分を置換するsub()subn()
  • パターンで文字列を分割するsplit()
  • 正規表現オブジェクトをコンパイルするcompile()

まず、reをインポートしてソースとなる文字列を準備する。

import re

s = 'one two one two'
スポンサーリンク

文字列の先頭がパターンにマッチするかを調べるmatch()

re.match()は文字列の先頭がパターンにマッチするかどうかを調べる。

m = re.match('one', s)
print(m)
# <_sre.SRE_Match object; span=(0, 3), match='one'>

マッチする場合はmatchオブジェクトを返す。matchオブジェクトはgroup()start()end()span()などのメソッドを持ち、マッチした文字列やその位置などを返す。

print(m.group())
print(m.start())
print(m.end())
print(m.span())
# one
# 0
# 3
# (0, 3)

group()メソッドはパターンにマッチした全体を返すが、パターンの一部分を()で囲んでおくと、groups()メソッドを使って、()で囲まれた部分にマッチしたそれぞれの文字列をタプルで取得できる。

m = re.match('(one) (two)', s)
print(m)
print(m.group())
print(m.groups())
# <_sre.SRE_Match object; span=(0, 7), match='one two'>
# one two
# ('one', 'two')

先頭にマッチする文字列がない場合はNoneを返す。

m = re.match('two', s)
print(m)
# None

re.search()は先頭にない文字列も探すことができる。re.match()と同じく、マッチする場合はmatchオブジェクトを返す。

m = re.search('one', s)
print(m)
# <_sre.SRE_Match object; span=(0, 3), match='one'>

m = re.search('two', s)
print(m)
# <_sre.SRE_Match object; span=(4, 7), match='two'>

文字列中にマッチする部分が複数あっても、返すのは最初にマッチした部分のみ。

マッチする部分すべてをリストで返すfindall()

re.findall()は、マッチする部分が複数ある場合、マッチした文字列すべてをリストにして返す。返すのはmatchオブジェクトではないので注意。

m = re.findall('one', s)
print(m)
# ['one', 'one']

m = re.findall('one two', s)
print(m)
# ['one two', 'one two']

マッチする部分すべてをイテレータで返すfinditer()

re.finditer()はマッチする部分すべてをmatchオブジェクトのイテレータで返す。ただのリストを返すre.findall()とは違い、matchオブジェクトを得られるので、マッチした位置なども取得することができる。

m = re.finditer('one', s)
print(m)
# <callable_iterator object at 0x10e786470>

for match in m:
    print(match)
# <_sre.SRE_Match object; span=(0, 3), match='one'>
# <_sre.SRE_Match object; span=(8, 11), match='one'>

マッチした部分を置換するsub()、subn()

re.sub()を使うと、マッチした部分を他の文字列に置換することができる。

m = re.sub('one', 'ONE', s)
print(m)
# ONE two ONE two

m = re.sub('one two', 'xxx', s)
print(m)
# xxx xxx

パターンの一部を()で囲むと、置換後の文字列の中でマッチした文字列を使用することができる。

m = re.sub('(one) (two)', '\\1X\\2', s)
print(m)
# oneXtwo oneXtwo

m = re.sub('(one) (two)', r'\1X\2', s)
print(m)
# oneXtwo oneXtwo

\1\2が、それぞれ一つ目の()にマッチした部分と二つ目の()にマッチした部分に対応している。''または""で囲まれた通常の文字列だと\\1のように\をエスケープする必要があるが、r''のように先頭にrをつけるraw文字列の場合は\1でOK。

置換後の文字列と置換された部分の個数とのタプルで返すre.subn()関数もある。

m = re.subn('one', 'ONE', s)
print(m)
# ('ONE two ONE two', 2)

文字列の置換についての詳細は以下の記事を参照。

パターンで文字列を分割するsplit()

re.split()はパターンにマッチした部分で文字列を分割し、リストにして返す。

m = re.split(' ', s)
print(m)
# ['one', 'two', 'one', 'two']

文字列の分割についての詳細は以下の記事を参照。

正規表現オブジェクトをコンパイルするcompile()

同じパターンを繰り返し使用する場合は、re.compile()で、あらかじめパターンをコンパイルして正規表現オブジェクトを生成したほうがよい。

正規表現オブジェクトのメソッドとして、上で紹介したmatch()sub()などを使うことができる。

p = re.compile('one')

m = p.match(s)
print(m)
# <_sre.SRE_Match object; span=(0, 3), match='one'>

m = p.findall(s)
print(m)
# ['one', 'one']

m = p.sub('ONE', s)
print(m)
# ONE two ONE two
スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事