19. 正規表現

図解!Python 正規表現の徹底解説!(文字列の抽出と置換など)

更新日:

正規表現とは、文字列をあるパターン化された記号で表現する記述方法で、指定したパターンに当てはまる文字列を検索や置換するのに利用します。

 
正規表現は様々な利用方法がありますが、例えば、次のような事に使うことができます。

  • 顧客の住所や電話番号の一覧から、特定の住所、郵便番号や電話番号などを抜き出したい。もしくは、正しい形式になっているかバリデーション(チェック)したい。
  • 大量の文章の中から特定の文字列を検索し、別の文字列に置換したい。
  • WEBスクレイピングで取得したWEBページの情報の中から、特定の情報を抽出したい。

 
この記事では、Pythonにおける正規表現の使い方について、初心者でも理解しやすいように、丁寧に解説していきたいと思います。

 
 

著書紹介(清水 義孝)

好評発売中!!

正規表現の書き方と使い方

正規表現は、文字列をあるパターン化された記号で表現する記述方法で、指定したパターンに当てはまる文字列を検索や置換するのに利用します。

 
例えば、あるURL”http://www.amazon.co.jp/dp/B07T9TCPZX”から、ホスト名にあたる” http://www.amazon.co.jp/”までを抽出する正規表現は、次のように記述します。
 

※突然、難しそうな表現が出てきましたが、後で1つ1つ丁寧に解説していきますので、ご安心ください。

 
これをPythonのコードでは次のように記述します。

http://www.amazon.co.jp/

 
最初の1行では、Pythonの正規表現のモジュールreをインポートします。

import re

 
次にホスト名を抽出するURLを、変数URLに格納しています。

URL = "http://www.amazon.co.jp/dp/B07T9TCPZX"

 
そして、正規表現のパターンを記述し、変数patternに格納します。正規表現については、後で詳しく説明いたします。

pattern = "https?://[^/]+/"

 
そして、match関数に変数patternとURLを渡し、実行結果を変数resに格納しています。

res = re.match(pattern, URL)

 
正規表現の関数はいくつかありますが、ここでは先頭からパターンに一致しているかチェックするmatch関数を使っています。正規表現で使う関数についても、別途説明いたします。

 
最後に実行結果を格納した変数resの中身をprintで表示しています。

print(res.group())

 
そして表示された結果が以下になります。URLの内、ホスト名までが抽出されていることがわかります。

http://www.amazon.co.jp/

 
実行結果は、パターンに一致するものがあればmatchオブジェクトというもので返ってきます。ここでは、matchオブジェクトのメソッドの1つであるgroupで、マッチした文字列を表示しました。

 
matchオブジェクトのメソッドには、次のようなものがあります。

メソッド説明
group()マッチした文字列を取得する。
span()マッチした文字列の開始、終了位置を取得する。
start()マッチした文字列の開始位置を取得する。
end()マッチした文字列の終了位置を取得する。

※開始位置は、1文字目は0から始まります。

 
これらが正規表現を使ってパターンに一致する文字列を抽出する一連の処理になります。
 
以降の章では、

  • 正規表現で使う関数の種類と使い方
  • 正規表現におけるパターンの記述方法

を解説していきたいと思います。

 
 

著書紹介(清水 義孝)

好評発売中!!

正規表現で使う関数の種類と使い方(文字列の抽出と置換)

正規表現で使う関数には、次のものがあります。

関数説明
match先頭の文字列からパターンに一致するものを検索する。
search先頭に限らずパターンに一致するものがあるかを確認する。
※但し、複数一致しても1つ目だけを返す。
findallパターンに一致するものを全てリストで返す。
※位置情報(開始、終了)は取得不可。
finditerパターンに一致するものを全てmatchオブジェクトで取得することができる。
※位置情報(開始、終了)も取得可。
fullmatch文字列全体が一致しているかを確認する。
subパターンに一致した文字列を別の文字列に置き換える(置換)

 
ここでは、それぞれの関数について順に解説していきましょう。

 
 

match: 先頭の文字列からパターンに一致するものを検索

match関数は、先頭の文字列からパターンに一致するものを検索する際に利用し、次のように記述します。

re.match(正規表現のパターン, 検索対象の文字列)

一致するものがあった場合、matchオブジェクトを返します。また一致するものが無かった場合、Noneが返ってきます。
 
注意点としては、あくまでも先頭の文字列から検索しますので、文字列の途中に一致するものがあっても、一致したとはみなされません。

 
 
まず簡単な正規表現を使っていくつかの例を確認していきましょう。

 
正規表現では、.(ドット)は任意の1文字を示します。ここでは、正規表現のパターンとして”x.y”(xとyの間に任意の1文字がある)が、ある文字列の先頭に含まれているかチェックしてみましょう。

 
match関数に対して、正規表現のパターン”x.y”と、文字列”xyz”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

<_sre.SRE_Match object; span=(0, 3), match='xyz'>

一致した結果として、matchオブジェクトの内容が表示されました。spanでは一致した文字列の範囲(開始位置、終了位置)が、matchには一致した文字列が表示されています。

 
 
今度は、文字列”vwxyz”を渡してみましょう。

None

結果は一致せず、Noneが表示されました。

 
このようにmatch関数は、あくまでも先頭の文字列から検索しますので、文字列の途中に一致するものがあっても、一致したとはみなされません。

 
 

search: 先頭に限らずパターンに一致するものを検索

search関数は、先頭に限らずパターンに一致するものがあるかを検索します。但し、一致したものが複数あっても、1つ目だけを返します。

re.search(正規表現のパターン, 検索対象の文字列)

search関数もmatch関数と同様に、一致するものがあった場合matchオブジェクトを返します。また一致するものが無かった場合、Noneが返ってきます。

 
 
まずいくつかの例を確認していきましょう。

 
search関数に対して、正規表現のパターン”x.y” (xとyの間に任意の1文字がある)と、文字列”vwxyz”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

<_sre.SRE_Match object; span=(2, 5), match='xyz'>

search関数では文字列の途中でも一致するものがあれば一致したとみなされます。一致した結果として、matchオブジェクトの内容が表示されました。

 
今度は、文字列"vwxyz vwxyz"を渡してみましょう。一致する箇所が2つ含まれているようです。

<_sre.SRE_Match object; span=(2, 5), match='xyz'>

一致した結果としてmatchオブジェクトが返ってきました。但し、一致した箇所としてspanには(2,5)と表示されています。

 
つまり、search関数では、2つ一致するものがあっても、返ってくるのは最初のものだけになります。複数取得する場合、次のfindall関数を使うことになります。

 
 

findall: パターンに一致するものを全てリストで返す

findall関数は、パターンに一致するものを全てリストで返します。

re.findall(正規表現のパターン, 検索対象の文字列)

但し、返ってくるのはリストになりますので、マッチオブジェクトのように一致した位置の情報までは取得できません。一致した位置の情報も必要な場合、finditer関数を使うことになります。

 
 
例を確認していきましょう。

 
findall関数に対して、正規表現のパターン”x.y” (xとyの間に任意の1文字がある)と、文字列"vwxyz vwxyz xaz xbz"を引数として渡し、返ってきたリストの内容をprintで表示します。

['xyz', 'xyz', 'xaz', 'xbz']

パターンに一致した全てのものがリストで表示されました。

 
 

finditer: パターンに一致するものを全てmatchオブジェクトで取得する

finditer関数は、パターンに一致するものを全てイテレータというもので返します。その要素はmatchオブジェクトになりますので、一致した文字列だけでなく、開始位置、終了位置などmatchオブジェクトの内容を表示することができます。

re.finditer(正規表現のパターン, 検索対象の文字列)

一致した位置の情報も必要な場合、finditer関数を使いましょう。

 
 
例を確認していきましょう。

 
finditer関数に対して、正規表現のパターン”x.y” (xとyの間に任意の1文字がある)と、文字列"vwxyz vwxyz xaz xbz"を引数として渡し、返ってきたイテレータの内容をfor文を使ってprintで表示します。

<_sre.SRE_Match object; span=(2, 5), match='xyz'>
<_sre.SRE_Match object; span=(8, 11), match='xyz'>
<_sre.SRE_Match object; span=(12, 15), match='xaz'>
<_sre.SRE_Match object; span=(16, 19), match='xbz'>

パターンに一致した全てのものについて、matchオブジェクトが表示されました。

 
 

fullmatch: 文字列全体が一致しているかを確認(完全一致)

fullmatch関数は、文字列の一部では無く、全体がパターンに完全一致しているかを確認するのに利用します。

re.fullmach(正規表現のパターン, 検索対象の文字列)

完全一致するものがあった場合matchオブジェクトを返します。また完全一致するものが無かった場合、Noneが返ってきます。

 
 
まずいくつかの例を確認していきましょう。

 
fullmatch関数に対して、正規表現のパターン”x.y” (xとyの間に任意の1文字がある)と、文字列”vwxyz”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

None

文字列“vwxyz”の中には、部分的に”x.z”に一致する”xyz”が含まれますが、文字列全体としては完全一致しませんので、Noneが返ってきます。

 
 
今度は、文字列"xyz "を渡してみましょう。

<_sre.SRE_Match object; span=(0, 3), match='xyz'>

完全一致した結果としてmatchオブジェクトが返ってきました。このようにfullmatchでは、文字列全体がパターンに完全一致する場合のみ、matchオブジェクトが返ってきます。

 
 

sub: パターンに一致した文字列を別の文字列に置き換え(置換)

今まではパターンに一致するものを検索していましたが、今度は一致するものを別の文字列に置き換える関数を紹介します。sub関数は、パターンに一致している箇所を置換後の文字列に置き換えます。

re.sub(正規表現のパターン, 置換後の文字列, 検索対象の文字列)

一致するものがあった場合、置換処理をした後の文字列が返ってきます。

 
 
sub関数に対して、正規表現のパターン”x.y” (xとyの間に任意の1文字がある)と、置換後の文字列”abc”、文字列”vwxyz”を引数として渡し、返ってきた置換処理後の内容をprintで表示します。

vwabc

文字列“vwxyz”の内、パターンに一致した”xyz”が”abc”に置き換えられているのがわかります。

 
 

著書紹介(清水 義孝)

好評発売中!!

正規表現のパターンを表す記号一覧と記述方法

次に正規表現におけるパターンの記号一覧と記述方法を確認していきましょう。これらは、いくつかの分類に分けることができます。

 

文字列の先頭・末尾を指定する記号一覧

これらの記号は、先頭から、もしくは、末尾から指定したパターンに一致するかを指定します。

記号説明
^文字列の先頭からパターンに一致するかを判定
例を表示!
search関数に対して、正規表現のパターン”^ab”と、文字列”abcde”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。
<_sre.SRE_Match object; span=(0, 2), match='ab'>

一致した結果として、matchオブジェクトの内容が表示されました。matchから先頭の文字’ab’が一致したことがわかります。

 
 
一方で、文字列"xyz abcde"を渡すとどうなるでしょうか。

None

パターンに一致せず、Noneが返ってきました。”^ab”により、先頭にabが存在するか否かを元に判定しますので、不一致となりました。

 

$文字列の末尾からパターンに一致するかを判定
例を表示!
search関数に対して、正規表現のパターン”de$”と、文字列”abcde”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

<_sre.SRE_Match object; span=(3, 5), match='de'>

末尾の文字’de’が一致したことがわかります。

 
 
今度は、文字列"abcde xyz"を渡してみます。

None

するとパターンに一致せず、Noneが返ってきました。”de$”により、文字列の末尾にdeが存在するか否かを元に判定しますので、不一致となりました。

 

 

繰り返し回数を指定する記号一覧

これらの記号は、直前の指定された文字列が繰り返し現れる回数を指定します。

記号説明
?0回もしくは1回
例を表示!
search関数に対して、正規表現のパターン”xy?”と、文字列”x”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。
<_sre.SRE_Match object; span=(0, 1), match='x'>

ここでは’x’が一致したようです。

 
正規表現のパターンとして、”xy?”が指定されているので、”?”の直前の”y”が0回、もしくは1回繰り返される場合、一致したとみなされます。つまり、”xy”、もしくは、”x”の場合、一致と判定されます。

 
 
今度は、文字列"xy"を渡してみます。

<_sre.SRE_Match object; span=(0, 2), match='xy'>

‘xy’が一致したようです。

 
 
さらに文字列"xyy"を渡してみます。

<_sre.SRE_Match object; span=(0, 2), match='xy'>

すると先ほどと同じ結果が返ってきました。つまりyの繰り返し回数の指定が0~1回までですので、”xy”までが一致し、残りの”y”は一致した中には含まれません。

 

*0回以上
例を表示!
正規表現のパターンとして、”xy*”を指定すると、”*”の直前の”y”が0回以上繰り返される場合、一致したとみなされます。つまり、”x”、”xy”、”xy…y”などが一致と判定されます。

 
search関数に対して、正規表現のパターン”xy*”と、文字列”x”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

<_sre.SRE_Match object; span=(0, 1), match='x'>
ここでは’x’が一致しました。

 
 
次に文字列”xyy”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

<_sre.SRE_Match object; span=(0, 3), match='xyy'>
’xyy’が一致しました。

 
 
そして文字列"xyyyyyyyy"を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

<_sre.SRE_Match object; span=(0, 9), match='xyyyyyyyy'>
’xyyyyyyyy’が一致しました。

 

+1回以上
例を表示!
search関数に対して、正規表現のパターン”xy+”と、文字列”x”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

None

ここでは一致せず、Noneが返ってきました。

 
正規表現のパターンとして、”xy+”が指定されているので、”+”の直前の”y”が1回以上繰り返される場合、一致したとみなされます。ここでは”y”が1つもありませんでしたので、不一致になりました。

 
 
今度は、文字列"xy"を渡してみます。

<_sre.SRE_Match object; span=(0, 2), match='xy'>
‘xy’が一致したようです。

 
 
さらに文字列"xyyyyyyyy"を渡します。

<_sre.SRE_Match object; span=(0, 9), match='xyyyyyyyy'>
‘xyyyyyyyy’が一致しました。

 

{m}m回
例を表示!
正規表現のパターンとして、”x{3}”を指定すると、”{3}”の直前の”x”が3回繰り返される場合、一致したとみなされます。つまり、”xxx”が一致と判定され、それ以外は不一致になります。

 
search関数に対して、正規表現のパターン”x{3}”と、文字列”xxx”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

<_sre.SRE_Match object; span=(0, 3), match='xxx'>

一致してmatchには’xxx’が返ってきました。

 
 
今度は、文字列"xxxx"を渡してみます。

<_sre.SRE_Match object; span=(0, 3), match='xxx'>

あくまでも”x”が3回に一致するので、‘xxx’までが一致し、4つ目の”x”は含まれません。

 
 
さらに文字列"xx"を渡します。

None

一致せずNoneが返ってきました。

 

{m,}m回以上
例を表示!
search関数に対して、正規表現のパターン"x{2,}"と、文字列”x”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

None

ここでは一致せず、Noneが返ってきました。

 
正規表現のパターンとして、”x{2,}”が指定されているので、”{2,}”の直前の”x”が2回以上繰り返される場合、一致したとみなされます。ここでは”x”が1つしかありませんので、不一致になりました。

 
 
今度は、文字列"xx"を渡してみます。

<_sre.SRE_Match object; span=(0, 2), match='xx'>

”x”が2回以上に一致するので、今回はmatchに’xx’が返ってきました。

 
 
ということで、文字列"xxxxxxxxxx"を渡しても同様に一致します。

<_sre.SRE_Match object; span=(0, 10), match='xxxxxxxxxx'>

 

{m,n}m回以上、n回まで
例を表示!
正規表現のパターンとして、”x{2,4}”を指定すると、”{2,4}”の直前の”x”が2回以上4回まで繰り返される場合、一致したとみなされます。つまり、”xx”、 ”xxx”、 ”xxxx”が一致と判定され、それ以外は不一致になります。

 
search関数に対して、正規表現のパターン”x{2,4}”と、文字列”x”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

None

“x”が1つですので不一致になり、Noneが返ってきました。

 
 
次に文字列"xx"を渡してみます。

<_sre.SRE_Match object; span=(0, 2), match='xx'>

”x”が2回以上に一致するので、今回はmatchに’xx’が返ってきました。

 
 
今度は、文字列"xxxx"を渡してみます。

<_sre.SRE_Match object; span=(0, 4), match='xxxx'>

”x”が2回以上4回までに当てはまるので、matchに’xxxx’が返ってきました。

 
 
そして文字列"xxxxxxxxxx"を渡してみます。

<_sre.SRE_Match object; span=(0, 4), match='xxxx'>

あくまでも”x”が2回以上4回までですので、matchに’xxxx’が返ってきます。残りの6つの”x”には当てはまりません。

 

 
 

グループ化単位で繰り返し回数を指定する記号一覧

これらの表記は、複数の文字列をグルーピングするのに利用します。そして、繰り返しを指定する記号と合わせて、グルーピングされた塊で指定された回数出現するかを判定するのに使われます。

記号説明
()()で囲われた文字列をグルーピングし、パターンに一致するかを判定
例を表示!
正規表現のパターンとして、”a(bc)*”を指定すると、”*”の直前の”(bc)”が0回以上繰り返される場合、一致したとみなされます。つまり、”(bc)”は1つのグループとしてみなされ、”a”、 ”abc”、 ”abcbc”などが一致と判定されます。

 
search関数に対して、正規表現のパターン”a(bc)*”と、文字列”a”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

<_sre.SRE_Match object; span=(0, 1), match='a'>

一致した結果として、matchオブジェクトの内容が表示されました。matchから文字’a’が一致したことがわかります。

 
 
今度は、文字列"abcbc"を渡してみます。

<_sre.SRE_Match object; span=(0, 5), match='abcbc'>

”(bc)”が0回以上に当てはまるので、matchに’abcbc’が返ってきました。

 
 
一方で、文字列"abcabc"を渡すとどうなるでしょうか。

<_sre.SRE_Match object; span=(0, 3), match='abc'>

“abc”だけがパターンに一致しました。あくまでも”(bc)”で1つのグループになり、繰り返される必要があります。

 
 
 
次の例として、正規表現のパターンとして、”a(bc){2,4}”を指定すると、”{2,4}”の直前の”(bc)”が2回以上4回まで繰り返される場合、一致したとみなされます。つまり、”(bc)”は1つのグループとしてみなされ、”abcbc”、 ”abcbcbc”、 ”abcbcbcbc”が一致と判定されます。

 
search関数に対して、正規表現のパターン”a(bc){2,4}”と、文字列”abcbc”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

<_sre.SRE_Match object; span=(0, 5), match='abcbc'>

”(bc)”が2回以上4回までに当てはまるので、matchに’abcbc’が返ってきました。

 
 
次に文字列"abcabc"を渡してみます。

None

パターンに一致せず、Noneが返ってきました。あくまでも”(bc)”で1つのグループになり、2回以上、4回までの範囲内で繰り返される必要があります。

 

 
 

集合(否定を含む)を指定する記号一覧

正規表現では、[]を使って「全てのアルファベット」など、特定のものの集まりを指定することもできます。またその集合以外を示す場合は、^を使って表現します。次の表に1つの例を挙げます。

記号説明
[0-9]全ての数字
例を表示!
正規表現のパターンとして、”[0-9]”を指定すると、0-9の数字の場合、一致したとみなされます。

 
search関数に対して、正規表現のパターン”[0-9]”と、文字列”a”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

None

パターンに一致せず、Noneが返ってきました。”[0-9]”で0から9までの数字の集合を指定していますので、それ以外のものは不一致となります。

 
 
今度は、数字"3"を渡してみます。

<_sre.SRE_Match object; span=(0, 1), match='3'>

今度はパターンに一致し、matchに’3’が返ってきました。

 

[a-zA-Z]全てのアルファベット
例を表示!
正規表現のパターンとして、”[a-zA-Z]”を指定すると、aからZまでの小文字のアルファベットと、AからZまでの大文字のアルファベットの場合、一致したとみなされます。

 
search関数に対して、正規表現のパターン” [a-zA-Z]”と、文字列”z”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

<_sre.SRE_Match object; span=(0, 1), match='z'>

パターンに一致し、matchに’z’が返ってきました。

 
 
次に、数字"7"を渡します。

None

パターンに一致せず、Noneが返ってきました。”[a-zA-Z]”で全てのアルファベットの集合を指定していますので、数字は不一致となります。

 

[a-zA-Z0-9]全てのアルファベットと数字
例を表示!
正規表現のパターンとして、”[a-zA-Z0-9]”を指定すると、aからZまでの小文字のアルファベットと、AからZまでの大文字のアルファベット、そして、0から9までの数字の場合、一致したとみなされます。

 
search関数に対して、正規表現のパターン” [a-zA-Z0-9]”と、文字列”z”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

<_sre.SRE_Match object; span=(0, 1), match='z'>

パターンに一致し、matchに’z’が返ってきました。

 
 
次に、数字"9"を渡します。

<_sre.SRE_Match object; span=(0, 1), match='9'>

こちらもパターンに一致し、matchに’9’が返ってきました。

 
 
そして、"_"(アンダーバー)を渡します。

None

パターンに一致せず、Noneが返ってきました。”[a-zA-Z0-9]”で全てのアルファベットと数字の集合を指定していますので、アンダーバーは不一致となります。

 

[^a-zA-Z0-9]全てのアルファベットと数字以外
集合に^(ハット)を付けると、集合の条件の否定となり、集合の条件を満たさない場合、一致となります。
例を表示!
例えば”[^a-zA-Z0-9]”を指定すると、aからZまでの小文字のアルファベットと、AからZまでの大文字のアルファベット、そして、0から9までの数字の場合、不一致になります。

 
search関数に対して、正規表現のパターン” [^a-zA-Z0-9]”と、文字列”z”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

None

パターンに一致せず、Noneが返ってきました。”[^a-zA-Z0-9]”で全てのアルファベットと数字以外を指定していますので、”z”は不一致となります。

 
 
そして、"_"(アンダーバー)を渡します。

<_sre.SRE_Match object; span=(0, 1), match='_'>

パターンに一致し、matchに’_’が返ってきました。

 

 
 

ORを指定する記号一覧

正規表現では、aかbのいずれかを指定するには、|(縦棒)を使って指定します。また[ ]を使っても指定することもできます。

記号説明
|例 a|b : a or b(aかbのいずれか)
例を表示!
正規表現のパターンとして、”a|b”を指定すると、aもしくはbの場合、一致したとみなされます。

 
search関数に対して、正規表現のパターン”a|b”と、文字列”ac”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

<_sre.SRE_Match object; span=(0, 2), match='ac'>

パターンに一致し、matchに’ac’が返ってきました。

 
 
今度は、文字列"bc"を渡してみます。

<_sre.SRE_Match object; span=(0, 2), match='bc'>

今度もパターンに一致し、matchに’bc’が返ってきました。

 
 
次に、文字列"dc"を渡してみます。

None

パターンに一致せず、Noneが返ってきました。”(a|b)”で”a”もしくは”b”を指定していますので、それ以外のもの(ここでは”d”)は不一致となります。

 

[ ]例 [ab] : a or b(aかbのいずれか)
例を表示!
正規表現のパターンとして、”[ab]”を指定すると、”a|b”と同様、aもしくはbの場合、一致したとみなされます。

 
search関数に対して、正規表現のパターン”[ab]”と、文字列”ac”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

<_sre.SRE_Match object; span=(0, 2), match='ac'>

パターンに一致し、matchに’ac’が返ってきました。

 
 
今度は、文字列"bc"を渡してみます。

<_sre.SRE_Match object; span=(0, 2), match='bc'>

今度もパターンに一致し、matchに’bc’が返ってきました。

 
 
次に、文字列"dc"を渡してみます。

None

パターンに一致せず、Noneが返ってきました。”[ab]”で”a”もしくは”b”を指定していますので、それ以外のもの(ここでは”d”)は不一致となります。

 

 
 

特殊シーケンス一覧(円マーク・バックスラッシュを用いた記号)

正規表現では、よく使われるパターンについては、特殊シーケンスと呼ばれる円マーク・バックスラッシュを使った簡易的な表現で置き換えることができます。

記号説明
\d全ての数字
[0-9]と同じ
例を表示!
正規表現のパターンとして、”\d”を指定すると、0-9の数字の場合、一致したとみなされます。

 
search関数に対して、正規表現のパターン”\d”と、文字列”a”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

None

パターンに一致せず、Noneが返ってきました。”\d”は”[0-9]”と同様、0から9までの数字の集合を指定していますので、それ以外のものは不一致となります。

 
 
今度は、数字"3"を渡してみます。

<_sre.SRE_Match object; span=(0, 1), match='3'>

今度はパターンに一致し、matchに’3’が返ってきました。

 

\D全ての数字以外
[^0-9]と同じ
例を表示!
正規表現のパターンとして、\dのdを大文字にし\Dとすると、条件の否定となり、全ての数字以外の場合に一致となり、0から9までの数字の場合、不一致になります。

 
search関数に対して、正規表現のパターン”\D”と、数字”7”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

None

パターンに一致せず、Noneが返ってきました。”\D”で全ての数字以外を指定していますので、”7”は不一致となります。

 
 
そして、"W"を渡します。

<_sre.SRE_Match object; span=(0, 1), match='W'>

パターンに一致し、matchに’W’が返ってきました。

 

\w全ての英数字と_(アンダーバー)
[a-zA-Z0-9_]と同じ
例を表示!
正規表現のパターンとして、”\w”を指定すると、全ての英数字とアンダーバーの場合、一致したとみなされます。

 
search関数に対して、正規表現のパターン”\w”と、文字列”A”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

<_sre.SRE_Match object; span=(0, 1), match='A'>

パターンに一致し、matchに’A’が返ってきました。

 
 
次に、文字列"_"を渡してみます。

<_sre.SRE_Match object; span=(0, 1), match='_'>

パターンに一致し、matchに’_’が返ってきました。

 
 
今度は、文字列"@"を渡してみます。

None

パターンに一致せず、Noneが返ってきました。”\w”は”[a-zA-Z0-9_]”と同様、英数字とアンダーバーの集合を指定していますので、それ以外のものは不一致となります。

 

\W全ての英数字と_(アンダーバー)以外
[^a-zA-Z0-9_]と同じ
例を表示!
正規表現のパターンとして、\wのWを大文字にし\Wとすると、条件の否定となり、全ての全ての英数字と_(アンダーバー)以外の場合に一致となり、全ての英数字と_(アンダーバー)の場合、不一致になります。

 
search関数に対して、正規表現のパターン”\W”と、数字”7”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

None

パターンに一致せず、Noneが返ってきました。”\W”で全ての英数字と_(アンダーバー)以外を指定していますので、”7”は不一致となります。

 
 
そして、"@"を渡します。

<_sre.SRE_Match object; span=(0, 1), match='@'>

パターンに一致し、matchに’@’が返ってきました。

 

\s空白
例を表示!
正規表現のパターンとして、”\s”を指定すると、空白(半角、全角)の場合、一致したとみなされます。

 
search関数に対して、正規表現のパターン”\s”と、半角スペース” ”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

<_sre.SRE_Match object; span=(0, 1), match=' '>

パターンに一致し、matchに’ ’が返ってきました。

 
 
今度は、全角スペース" "を渡してみます。

<_sre.SRE_Match object; span=(0, 1), match='\u3000'>

今度もパターンに一致し、matchに’u3000’が返ってきました。

 
 
次に、文字列"w"を渡してみます。

None

パターンに一致せず、Noneが返ってきました。”\s”は空白以外のものは不一致となります。

 

\S空白以外
例を表示!
正規表現のパターンとして、\sのsを大文字にし\Sとすると、条件の否定となり、空白(半角、全角)以外の場合に一致となり、空白の場合、不一致になります。

 
search関数に対して、正規表現のパターン”\S”と、半角スペース” ”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

None

パターンに一致せず、Noneが返ってきました。”\S”で空白以外を指定していますので、半角スペースは不一致となります。

 
 
そして、"@"を渡します。

<_sre.SRE_Match object; span=(0, 1), match='@'>

パターンに一致し、matchに’@’が返ってきました。

 

\A文字列の先頭
^と同じ
例を表示!
search関数に対して、正規表現のパターン”\Aab”と、文字列”abcde”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

<_sre.SRE_Match object; span=(0, 2), match='ab'>

一致した結果として、matchオブジェクトの内容が表示されました。matchから先頭の文字’ab’が一致したことがわかります。

 
 
一方で、文字列"xyz abcde"を渡すとどうなるでしょうか。

None

パターンに一致せず、Noneが返ってきました。”\Aab”により、先頭にabが存在するか否かを元に判定しますので、不一致となりました。

 

\Z文字列の末尾
$と同じ
例を表示!
search関数に対して、正規表現のパターン”de\Z”と、文字列”abcde”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

<_sre.SRE_Match object; span=(3, 5), match='de'>

末尾の文字’de’が一致したことがわかります。

 
 
今度は、文字列"abcde xyz"を渡してみます。

None

するとパターンに一致せず、Noneが返ってきました。”de\Z”により、文字列の末尾にdeが存在するか否かを元に判定しますので、不一致となりました。

 

 
 

正規表現のパターンをコンパイルする方法

正規表現ではパターンをコンパイルすることによって、同じパターンを効率的に繰り返し利用することができます。

 
コンパイルにはcompile()を使い、以下のように記述します。

pattern = re.compile(正規表現のパターン)
res = pattern.match(検索対象の文字列)

パターンをコンパイルした結果を、変数patternに格納しています。そして、変数patternを元に、match()で検索対象の文字列に対して、パターンに一致するか否かを判定しています。ここでは関数にmatch()を使いましたが、別の関数でも同様です。

 
一度パターンをコンパイルすることで、次のコードの検索対象の文字列や関数を変更しながら、同じパターンを使いまわすことができます。

res = pattern.match(検索対象の文字列)

 
 
compile()に対して、正規表現のパターン”xy+”を引数として渡し、返ってきた値を変数patternに格納します。 変数patternを元に、match()に対して、文字列”xyyyyyy”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

<_sre.SRE_Match object; span=(0, 7), match='xyyyyyy'>

 
次回、同じパターンで別の文字列を検索する場合、次のように記述します。

<_sre.SRE_Match object; span=(3, 6), match='xyy'>

ここでは、一度コンパイルした結果を格納した変数pattはそのまま利用しています。そして検索対象の文字列や関数を変更して、同じパターンで検索しています。

 
 

著書紹介(清水 義孝)

好評発売中!!

特殊文字をエスケープする記号(\)

"*"や"?"のような特殊な文字を検索する場合、\(バックスラッシュ)を付ける必要があります。

 
例として、"?"を検索してみましょう。
search関数に対して、正規表現のパターン"\?"と、文字列"xy?"を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

<_sre.SRE_Match object; span=(2, 3), match='?'>

"\?"はバックスラッシュが付いており、"?"と見なされマッチしました。

 
 

貪欲マッチ・非貪欲マッチ

繰り返し回数を指定する記号 ? (0回もしくは1回)、*(0回以上)、+(1回以上)については、デフォルトでは貪欲マッチと呼ばれる、できるだけ長いテキストにマッチするよう検索されます。

 
例えば次のようなケースでは、マッチする文字列として次のようなものが考えられます。

re.search("<.*>", "<html><head></head><body></body></html>")
  • <html>
  • <html><head> など
  • <html><head>…</body></html>

但し、デフォルトでは、できるだけ長いテキストである3. にマッチします。ただ、正規表現を使う中で1.の一番短いテキストにマッチして欲しいケースが多々あります。

 
その場合、??、*?、+?と、各記号の後に?を付けることで、できるだけ短いテキストにマッチさせることができます。

 
 
search関数に対して、正規表現のパターン”<.*>”と、文字列”<html><head></head><body></body></html>”を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

<_sre.SRE_Match object; span=(0, 39), match='<html><head></head><body></body></html>'>

デフォルトでは、できるだけ長い文字列にマッチしようとするので、ここでは’<html><head></head><body></body></html>’がマッチしたようです。

 
 
今度は、できるだけ短いテキストにマッチするよう、パターンに"<.*?>"を渡してみます。

<_sre.SRE_Match object; span=(0, 6), match='<html>'>

すると先ほどとは異なり、’<html>’がマッチしたようです。このように、正規表現の各記号の後に?を付けることで、できるだけ短いテキストにマッチさせることができます。

 
 

フラグ引数

正規表現の関数やcomplie()ではフラグ引数を渡すことによって、マッチする条件を詳細にコントロールできるものがあります。

 
例えば、search()では次のように記述します。他の正規表現の関数も同様です。

res = re.search(正規表現のパターン, 検索対象の文字列, flags=フラグ引数)

 
またcompile()では、以下のように記述します。

pattern = re.compile(正規表現のパターン, flags=フラグ引数)

 
 

1.大文字・小文字を区別しないマッチング(re.IGNORECASE)

正規表現の関数に対して、フラグ引数re.IGNORECAEを渡すことにより、大文字・小文字を区別しないマッチングを行ことができます。

 
search関数に対して、正規表現のパターン"[a-z]+"と、文字列"xyzXYZ"を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

<_sre.SRE_Match object; span=(0, 3), match='xyz'>

パターン"[a-z]+"として小文字だけを指定しましたので、ここでは小文字だけがマッチしたようです。

 
 
今度は、フラグ引数に大文字・小文字を区別しないre.IGNORECAEを渡します。

<_sre.SRE_Match object; span=(0, 6), match='xyzXYZ'>

ここでは'xyzXYZ'と大文字も含めてマッチしたようです。

 
 

2. 各行の先頭・末尾にマッチング(re.MULTILINE)

検索対象の文字列が複数行に渡って記述されている場合、通常、パターン'^' は文字列の先頭にしかマッチしませんが、フラグ引数にre.MULTILINEを渡すことで、各行の先頭にもマッチさせることができます。
同様に、パターン'$'は文字列の末尾にしかマッチしませんが、フラグ引数にre.MULTILINEを渡すことで、各行の末尾にもマッチさせることができます。

 
 
findall関数に対して、正規表現のパターン"^[a-z]+"と、複数行に渡る文字列を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

['abc']

パターン"^[a-z]+"として文字列の先頭を指定しましたので、ここでは先頭の’abc’だけがマッチしたようです。

 
 
今度は、各行の先頭にもそれぞれマッチするよう、フラグ引数にre.MULTILINEを渡します。

['abc', 'def', 'hij']

ここでは各行の先頭とマッチしました。

 
 

パターンを視覚的に分割し、コメントを付加できる(re.VERBOSE)

正規表現のパターンが長くなった場合、コメントを付けて、わかりやすくする必要があります。
そのような場合に、complie()の引数としてre.VERBOSEを付けることにより、複数行に渡って記述したパターンの間にコメントを挿入することができます。

 
例えば、正規表現のパターン”[0-9]{4}\/[0-9]{1,2}\/[0-9]{1,2}”を使って、検索対象の文字列から日付(yyyy/mm/dd)を抽出するケースを考えます。

 
このような長文のパターンについては、"""(ダブルクォーテーションを3つ)や'''(シングルクォーテーションを3つ)で囲うことにより、複数行に渡って記述することができます。

 
そして、 これらの年、月、日などの論理的な区切り毎に#(ハッシュ)を用いてコメントを挿入していきます。但し、このままでは#(ハッシュ)以降の箇所がコメントと認識されませんので、うまく日付にマッチさせることができません。

 
そこでcompile()の引数として、re.VERBOSEを渡します。これにより、#年/、#月/、#日がコメントとして扱われ、パターンの中には含まれなくなります。

 
先ほどコンパイルしたパターンを用いて、findall()に検索対象の文字列"The date is 2020/10/23"を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

['2020/10/23']

日付にマッチし、'2020/10/23'が返ってきました。パターンの文字列に含まれる、#年/、#月/、#日の箇所は正規表現のパターンには含まれず、コメントとして扱われていることがわかります。

 
 

パターンをグループ化し名前を付けて参照する方法

正規表現のパターンはグループ化し、グループ毎に名前を付けて、それぞれにマッチしたものを名前で参照することができます。
 
グループ化は、パターンのグルーピングしたい単位に、(?P<name>...) を付けていきます。<name>のnameにグループの名前を記述し、... の箇所にグループに含まれるパターンを記述します。
 
マッチしたものを参照するには、matchオブジェクトのメソッドgroup()に対して、先ほど付けたグループの名前nameを引数として渡します。

 
 
ここでも例として、正規表現のパターン”[0-9]{4}\/[0-9]{1,2}\/[0-9]{1,2}”を使って、検索対象の文字列から日付(yyyy/mm/dd)を抽出するケースを考えます。そして、 これらの年、月、日などの論理的な区切り毎に(?P<name>...)を用いてグループ化していきます。

 
例えば、年にマッチするパターンは”[0-9]{4}”になりますので、(?P<name>...)のnameには”year”を、…の箇所には”[0-9]{4}”を挿入します。またグループに関係の無い” \/”は、(?P<name>...)の外に記述します。

 
先ほどコンパイルしたパターンを用いて、findall()に検索対象の文字列"The date is 2020/10/23"を引数として渡し、返ってきたmatchオブジェクトの内容をprintで表示します。

 
その際にgoup()に対して引数”year”、”month”、”date”を渡します。

Out: 2020
        10
        23

すると、年、月、日のパターンにマッチした値がそれぞれ表示されました。このようにして正規表現のパターンをグループ化し、マッチした箇所をグループ毎に参照することができます。

 
 
関連記事です。
Pythonに関する重要なトピック全般について学んでいきたいと考えておられる方には、次のリンクをお勧めします。

 

-19. 正規表現

Copyright© AI-interのPython3入門 , 2019 All Rights Reserved.