Python3 正規表現

正規表現は特別な文字列で、文字列が何らかのパターンにマッチするかを簡単に確認するのに役立ちます。

Python では、reモジュールを使用して正規表現を処理します。

re モジュールは、文字列内でパターンマッチ、検索、置換操作を行うための一連の関数を提供します。

reモジュールにより、Python 言語は完全な正規表現機能を備えています。

この章では、Python でよく使われる正規表現処理関数を主に紹介します。正規表現に詳しくない場合は、当サイトの正規表現 - チュートリアル。


re.match関数

re.match は文字列の先頭からパターンのマッチを試みます。先頭でマッチしない場合、match() は None を返します。

関数構文:

re.match(pattern, string, flags=0)

関数パラメータの説明:

パラメータ説明
patternマッチする正規表現
stringマッチさせる文字列。
flagsフラグ。正規表現のマッチ方法を制御します。例:大文字小文字の区別、複数行マッチなど。参照:正規表現修飾子 - オプションのフラグ

マッチが成功するとre.matchメソッドはマッチオブジェクトを返し、それ以外の場合はNone。

使用できるのはgroup(num) 或 groups()マッチオブジェクト関数でマッチ式を取得できます。

マッチオブジェクトのメソッド説明
group(num=0)マッチした式全体の文字列。group() には複数のグループ番号を一度に入力でき、その場合、それらのグループに対応する値を含むタプルを返します。
groups()1 から含まれるグループ番号までのすべてのグループ文字列を含むタプルを返します。

例

#!/usr/bin/python import re print(re.match('www', 'www.example.com').span()) # 先頭位置でマッチ print(re.match('com', 'www.example.com')) # 先頭位置ではないマッチ

上記の例の実行出力結果は次のとおりです:

(0, 3)
None

例

#!/usr/bin/python3 import re line = "Cats are smarter than dogs" # .* は改行(\n、\r)以外の任意の1文字または複数文字にマッチすることを示します # (.*?) は「非貪欲」モードを示し、最初にマッチした部分文字列のみを保存します matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I) if matchObj: print ("matchObj.group() : ", matchObj.group()) print ("matchObj.group(1) : ", matchObj.group(1)) print ("matchObj.group(2) : ", matchObj.group(2)) else: print ("No match!!")

上記の例の実行結果は次のとおりです:

matchObj.group() :  Cats are smarter than dogs
matchObj.group(1) :  Cats
matchObj.group(2) :  smarter

re.searchメソッド

re.search は文字列全体をスキャンし、最初に成功したマッチを返します。

関数構文:

re.search(pattern, string, flags=0)

関数パラメータの説明:

パラメータ説明
patternマッチする正規表現
stringマッチさせる文字列。
flagsフラグ。正規表現のマッチ方法を制御します。例:大文字小文字の区別、複数行マッチなど。参照:正規表現修飾子 - オプションのフラグ

マッチが成功すると re.search メソッドはマッチオブジェクトを返し、それ以外の場合は None を返します。

group(num) または groups() マッチオブジェクト関数を使用してマッチ式を取得できます。

マッチオブジェクトのメソッド説明
group(num=0)マッチした式全体の文字列。group() には複数のグループ番号を一度に入力でき、その場合、それらのグループに対応する値を含むタプルを返します。
groups()1 から含まれるグループ番号までのすべてのグループ文字列を含むタプルを返します。

例

#!/usr/bin/python3 import re print(re.search('www', 'www.example.com').span()) # 先頭位置でマッチ print(re.search('com', 'www.example.com').span()) # 先頭位置ではないマッチ

上記の例の実行出力結果は次のとおりです:

(0, 3)
(11, 14)

例

#!/usr/bin/python3 import re line = "Cats are smarter than dogs" searchObj = re.search( r'(.*) are (.*?) .*', line, re.M|re.I) if searchObj: print ("searchObj.group() : ", searchObj.group()) print ("searchObj.group(1) : ", searchObj.group(1)) print ("searchObj.group(2) : ", searchObj.group(2)) else: print ("Nothing found!!")
上記の例の実行結果は次のとおりです:
searchObj.group() :  Cats are smarter than dogs
searchObj.group(1) :  Cats
searchObj.group(2) :  smarter

re.match と re.search の違い

re.match文字列の先頭のみをマッチします。文字列の先頭が正規表現に合わない場合、マッチは失敗し、関数は None を返します。一方、re.search文字列全体をマッチし、マッチが見つかるまで続けます。

例

#!/usr/bin/python3 import re line = "Cats are smarter than dogs" matchObj = re.match( r'dogs', line, re.M|re.I) if matchObj: print ("match --> matchObj.group() : ", matchObj.group()) else: print ("No match!!") matchObj = re.search( r'dogs', line, re.M|re.I) if matchObj: print ("search --> matchObj.group() : ", matchObj.group()) else: print ("No match!!")
上記の例の実行結果は次のとおりです:
No match!!
search --> matchObj.group() :  dogs

検索と置換

Python の re モジュールは、文字列内のマッチ項目を置換するための re.sub を提供します。

構文:

re.sub(pattern, repl, string, count=0, flags=0)

パラメータ:

  • pattern : 正規表現のパターン文字列。
  • repl : 置換する文字列、または関数。
  • string : 検索・置換される元の文字列。
  • count : パターンマッチ後の置換の最大回数。デフォルトの 0 はすべてのマッチを置換することを示します。
  • flags : コンパイル時に使用するマッチモード。数値形式。

最初の3つは必須パラメータ、後の2つはオプションパラメータです。

例

#!/usr/bin/python3 import re phone = "2004-959-559 # これは電話番号です" # コメントを削除 num = re.sub(r'#.*$', "", phone) print ("電話番号 :", num) # 数字以外の内容を削除 num = re.sub(r'\D', "", phone) print ("電話番号 :", num)

上記の例の実行結果は次のとおりです:

电话号码 :  2004-959-559 
电话号码 :  2004959559

repl パラメータは関数です

次の例では、文字列内のマッチした数字を2倍します:

例

#!/usr/bin/python import re # マッチした数字を2倍します def double(matched): value = int(matched.group('value')) return str(value * 2) s = 'A23G4HFD567' print(re.sub('(?P<value>\d+)', double, s))

実行出力結果は次のとおりです:

A46G8HFD1134

compile 関数

compile 関数は正規表現をコンパイルし、正規表現(Pattern)オブジェクトを生成して、match() と search() の2つの関数で使用できるようにします。

構文形式は次のとおりです:

re.compile(pattern[, flags])

パラメータ:

  • pattern : 文字列形式の正規表現
  • flags はオプションで、大文字小文字の無視、複数行モードなどのマッチモードを指定します。具体的なパラメータは次のとおりです:
    • re.IGNORECASE または re.I- マッチを大文字小文字に依存しないようにします
  • re.L は特殊文字セット \w, \W, \b, \B, \s, \S が現在の環境に依存することを示します
  • re.MULTILINE または re.M - 複数行モード。^ と $ の動作を変更し、文字列の各行の先頭と末尾にマッチするようにします。
  • re.DOTALL または re.S -.改行文字を含む任意の文字にマッチさせます。
  • re.ASCII - \w, \W, \b, \B, \d, \D, \s, \S を ASCII 文字のみにマッチさせます。
  • re.VERBOSE または re.X - 空白とコメントを無視し、複雑な正規表現をより明確に整理できます。

これらのフラグは単独で使用することも、ビットごとの OR(|)で組み合わせて使用することもできます。例えば、re.IGNORECASE | re.MULTILINE は大文字小文字の無視と複数行モードを同時に有効にすることを示します。

例

例

>>>import re >>> pattern = re.compile(r'\d+') # 少なくとも1つの数字にマッチする >>> m = pattern.match('one12twothree34four') # 先頭を検索、マッチなし >>> print( m ) None >>> m = pattern.match('one12twothree34four', 2, 10) # 'e' の位置からマッチを開始、マッチなし >>> print( m ) None >>> m = pattern.match('one12twothree34four', 3, 10) # '1' の位置からマッチを開始、ちょうどマッチ >>> print( m ) # Match オブジェクトを返す <_sre.SRE_Match object at 0x10a42aac0> >>> m.group(0) # 0 は省略可能 '12' >>> m.start(0) # 0 は省略可能 3 >>> m.end(0) # 0 は省略可能 5 >>> m.span(0) # 0 は省略可能 (3, 5)

上記では、マッチが成功すると Match オブジェクトが返されます。ここで:

  • group([group1, …])メソッドは1つ以上のグループマッチ文字列を取得するために使用します。マッチした部分文字列全体を取得する場合は、直接group() 或 group(0);
  • start([group])メソッドは、グループマッチした部分文字列が文字列全体内で開始する位置(部分文字列の最初の文字のインデックス)を取得します。パラメータのデフォルト値は 0 です。
  • end([group])メソッドは、グループマッチした部分文字列が文字列全体内で終了する位置(部分文字列の最後の文字のインデックス+1)を取得します。パラメータのデフォルト値は 0 です。
  • span([group])メソッドは返します(start(group), end(group))。

もう1つの例を見てみましょう:

例

>>>import re >>> pattern = re.compile(r'([a-z]+) ([a-z]+)', re.I) # re.I は大文字小文字を無視することを示します >>> m = pattern.match('Hello World Wide Web') >>> print( m ) # マッチ成功、Match オブジェクトを返します <_sre.SRE_Match object at 0x10bea83e8> >>> m.group(0) # マッチに成功した部分文字列全体を返す 'Hello World' >>> m.span(0) # マッチに成功した部分文字列全体のインデックスを返す (0, 11) >>> m.group(1) # 最初のグループがマッチした部分文字列を返す 'Hello' >>> m.span(1) # 最初のグループがマッチした部分文字列のインデックスを返す (0, 5) >>> m.group(2) # 2番目のグループがマッチした部分文字列を返す 'World' >>> m.span(2) # 2番目のグループがマッチした部分文字列のインデックスを返す (6, 11) >>> m.groups() # (m.group(1), m.group(2), ...) と等価 ('Hello', 'World') >>> m.group(3) # 3番目のグループは存在しない Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: no such group

findall

文字列内で正規表現にマッチするすべての部分文字列を検索し、リストを返します。複数のマッチパターンがある場合はタプルのリストを返し、マッチするものが見つからない場合は空のリストを返します。

注意:match と search は1回だけマッチし、findall はすべてマッチします。

構文は次のとおりです:

re.findall(pattern, string, flags=0)
或
pattern.findall(string[, pos[, endpos]])

パラメータ:

  • patternマッチパターン。
  • stringマッチ対象の文字列。
  • posオプションのパラメータ。文字列の開始位置を指定します。デフォルトは 0 です。
  • endposオプションのパラメータ。文字列の終了位置を指定します。デフォルトは文字列の長さです。

文字列内のすべての数字を検索する:

例

import re result1 = re.findall(r'\d+','サンプル 123 google 456') pattern = re.compile(r'\d+') # 数字を検索 result2 = pattern.findall('サンプル 123 google 456') result3 = pattern.findall('run88oob123google456', 0, 10) print(result1) print(result2) print(result3)

出力結果:

['123', '456']
['123', '456']
['88', '12']

複数のマッチパターンの場合、タプルのリストを返します:

例

import re

result = re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10')
print(result)
[('width', '20'), ('height', '10')]

re.finditer

findall と似ています。文字列内で正規表現にマッチするすべての部分文字列を検索し、それらをイテレータとして返します。

re.finditer(pattern, string, flags=0)

パラメータ:

パラメータ説明
patternマッチする正規表現
stringマッチ対象の文字列。
flagsフラグ。正規表現のマッチ方法を制御します。例:大文字と小文字の区別、複数行マッチなど。参照:正規表現修飾子 - オプションフラグ

例

import re it = re.finditer(r"\d+","12a32bc43jf3") for match in it: print (match.group() )

出力結果:

12 
32 
43 
3

re.split

split メソッドは、マッチする部分文字列で文字列を分割し、リストを返します。使用形式は次のとおりです:

re.split(pattern, string[, maxsplit=0, flags=0])

パラメータ:

パラメータ説明
patternマッチする正規表現
stringマッチ対象の文字列。
maxsplit分割回数。maxsplit=1 で1回分割します。デフォルトは 0 で、回数制限はありません。
flagsフラグ。正規表現のマッチ方法を制御します。例:大文字と小文字の区別、複数行マッチなど。参照:正規表現修飾子 - オプションフラグ

例

>>>import re >>> re.split('\W+', 'サンプル, サンプル, サンプル.') ['サンプル', 'サンプル', 'サンプル', ''] >>> re.split('(\W+)', ' サンプル, サンプル, サンプル.') ['', ' ', 'サンプル', ', ', 'サンプル', ', ', 'サンプル', '.', ''] >>> re.split('\W+', ' サンプル, サンプル, サンプル.', 1) ['', 'サンプル, サンプル, サンプル.'] >>> re.split('a*', 'hello world') # マッチする文字列が見つからない場合、split は分割を行いません ['hello world']

正規表現オブジェクト

re.RegexObject

re.compile() は RegexObject オブジェクトを返します。

re.MatchObject

group() は RE にマッチした文字列を返します。

  • start()マッチの開始位置を返します
  • end()マッチの終了位置を返します
  • span()マッチ位置 (開始, 終了) を含むタプルを返します

正規表現修飾子 - オプションのフラグ

正規表現には、マッチのパターンを制御するオプションのフラグ修飾子を含めることができます。

以下のフラグは単独で使用することも、ビット単位の OR(|)で組み合わせて使用することもできます。例えば、re.IGNORECASE | re.MULTILINE は、大文字と小文字の区別を無視するモードと複数行モードを同時に有効にします。

修飾子説明例
re.IGNORECASE または re.Iマッチを大文字と小文字に依存しないようにします
import re
pattern = re.compile(r'apple', flags=re.IGNORECASE)
result = pattern.match('Apple')
print(result.group())  # 输出: 'Apple'
re.MULTILINE または re.M複数行マッチ。に影響します^と$、それらを文字列の各行の先頭と末尾にマッチさせます。
import re
pattern = re.compile(r'^\d+', flags=re.MULTILINE)
text = '123\n456\n789'
result = pattern.findall(text)
print(result)  # 输出: ['123', '456', '789']
re.DOTALL または re.S:使 .改行文字を含む任意の文字にマッチします。
import re
pattern = re.compile(r'a.b', flags=re.DOTALL)
result = pattern.match('a\nb')
print(result.group())  # 输出: 'a\nb'
re.ASCII\w, \W, \b, \B, \d, \D, \s, \S を ASCII 文字のみにマッチさせます。
import re
pattern = re.compile(r'\w+', flags=re.ASCII)
result = pattern.match('Hello123')
print(result.group())  # 输出: 'Hello123'
re.VERBOSE または re.X空白とコメントを無視し、複雑な正規表現をより明確に構成できます。
import re
pattern = re.compile(r'''
    \d+  # 匹配数字
    [a-z]+  # 匹配小写字母
''', flags=re.VERBOSE)
result = pattern.match('123abc')
print(result.group())  # 输出: '123abc'

正規表現パターン

パターン文字列は、特別な構文を使用して正規表現を表します。

文字と数字はそれ自体を表します。正規表現パターン内の文字と数字は、同じ文字列にマッチします。

多くの文字と数字は、前にバックスラッシュを付けると異なる意味を持ちます。

句読点はエスケープされた場合のみそれ自体にマッチし、それ以外の場合は特別な意味を表します。

バックスラッシュ自体はバックスラッシュでエスケープする必要があります。

正規表現には通常バックスラッシュが含まれるため、それらを表すには raw 文字列を使用するのが最善です。パターン要素(例:r'\t'、これは次と等価です\\t)は対応する特殊文字にマッチします。

次の表は、正規表現パターン構文の特殊要素を示しています。パターンとともにオプションのフラグパラメータを指定すると、一部のパターン要素の意味が変わります。

パターン説明
^文字列の先頭にマッチ
$文字列の末尾にマッチ。
.改行文字以外の任意の文字にマッチします。re.DOTALL フラグが指定されている場合は、改行文字を含む任意の文字にマッチできます。
[...]含まれる任意の1文字にマッチします。例: [amk] は 'a'、'm' または 'k' にマッチします
[^...][] 内にない文字:[^abc] は a、b、c 以外の文字にマッチします。
re*0個以上の式にマッチします。
re+1個以上の式にマッチします。
re?前の正規表現で定義された断片の0個または1個にマッチします。非貪欲(non-greedy)方式です
re{ n}前の式の n 個にマッチします。例: "o{2}" は "Bob" の "o" にはマッチしませんが、"food" の2つの "o" にはマッチします。
re{ n,}前の式の n 個以上にマッチします。例: "o{2,}" は "Bob" の "o" にはマッチしませんが、"foooood" のすべての "o" にはマッチします。"o{1,}" は "o+" と等価です。"o{0,}" は "o*" と等価です。
re{ n, m}前の正規表現で定義された断片に n 回から m 回マッチします。貪欲(greedy)方式です
a| ba または b にマッチ
(re)括弧内の式にマッチし、グループも表します
(?imx)正規表現には i、m、または x の3つのオプションフラグを含めることができます。括弧内の領域のみに影響します。
(?-imx)正規表現は i、m、または x のオプションフラグを無効にします。括弧内の領域のみに影響します。
(?: re)(...) に似ていますが、グループを表しません
(?imx: re)括弧内で i、m、または x のオプションフラグを使用します
(?-imx: re)括弧内で i、m、または x のオプションフラグを使用しません
(?#...)コメント。
(?= re)先読み肯定アサーション。含まれる正規表現(... で示す)が現在位置でマッチに成功すれば成功し、そうでなければ失敗します。ただし、含まれる式が一旦試行されると、マッチエンジンは一切前進しません。パターンの残りは、このアサーションの右側で試行されます。
(?! re)先読み否定アサーション。肯定のアサーションとは逆で、含まれる式が文字列の現在位置でマッチできない場合に成功します。
(?> re)マッチする独立したパターン。バックトラッキングを省略します。
\w数字・英字・アンダースコアにマッチ
\W数字・英字・アンダースコア以外にマッチ
\s任意の空白文字にマッチします。[\t\n\r\f] と等価です。
\S任意の非空白文字にマッチします
\d任意の数字にマッチします。[0-9] と等価です。
\D任意の非数字にマッチします
\A文字列の先頭にマッチ
\Z文字列の末尾にマッチします。改行がある場合は、改行前の文字列の末尾にのみマッチします。
\z文字列の末尾にマッチ
\G最後にマッチが完了した位置にマッチします。
\b単語の境界にマッチします。つまり、単語と空白の間の位置です。例えば、'er\b' は "never" の 'er' にマッチしますが、"verb" の 'er' にはマッチしません。
\B非単語境界にマッチします。'er\B' は "verb" の 'er' にマッチしますが、"never" の 'er' にはマッチしません。
\n, \t など。改行文字にマッチします。タブ文字にマッチします、など。
\1...\9n 番目のグループの内容にマッチします。
\10n 番目のグループの内容にマッチします(それがマッチした場合)。それ以外の場合は、8進数文字コードの式を指します。

正規表現の例

文字マッチ

例説明
python"python" にマッチします。

文字クラス

例説明
[Pp]ython "Python" または "python" にマッチ
rub[ye]"ruby" または "rube" にマッチ
[aeiou]角括弧内の任意の1文字にマッチ
[0-9]任意の数字にマッチします。
[a-z]任意の小文字にマッチ
[A-Z]任意の大文字にマッチ
[a-zA-Z0-9]任意の英字と数字にマッチ
[^aeiou]aeiou を除くすべての文字
[^0-9]数字以外のすべての文字にマッチ

特殊文字クラス

例説明
.「\n」以外の任意の1文字にマッチします。'\n' を含む任意の文字にマッチさせるには、'[.\n]' のようなパターンを使用します。
\d数字文字にマッチします。[0-9] と同等です。
\D 非数字文字にマッチします。[^0-9] と同等です。
\sスペース、タブ、フォームフィードなどを含む任意の空白文字にマッチします。[ \f\n\r\t\v] と同等です。
\S 任意の非空白文字にマッチします。[^ \f\n\r\t\v] と同等です。
\wアンダースコアを含む任意の単語文字にマッチします。'[A-Za-z0-9_]' と同等です。
\W任意の非単語文字にマッチします。'[^A-Za-z0-9_]' と同等です。
その他の拡張