このモジュールでは、 Perl で見られるものと同様な正規表現マッチング操作を提供しています。パターンと検索対象文字列の両方について、 8 ビット文字列と Unicode 文字列を同じように扱えます。
正規表現では、特殊な形式を表したり、特殊文字の持つ特別な意味を呼び出さずにその特殊な文字を使えるようにするために、バックスラッシュ文字 ('\') を使います。こうしたバックスラッシュの使い方は、 Python の文字列リテラルにおける同じバックスラッシュ文字と衝突を起こします。例えば、バックスラッシュ自体にマッチさせるには、パターン文字列として '\\\\' と書かなければなりません、というのも、正規表現は \\ でなければならず、さらに正規な Python 文字列リテラルでは各々のバックスラッシュを \\ と表現せねばならないからです。
正規表現パターンに Python の raw string 記法を使えばこの問題を解決できます。 'r' を前置した文字列リテラル内ではバックスラッシュを特別扱いしません。従って、 "\n" が改行一文字の入った文字列になるのに対して、 r"\n" は '\' と 'n' という二つの文字の入った文字列になります。通常、 Python コード中では、パターンをこの raw string 記法を使って表現します。
大抵の正規表現操作がモジュールレベルの関数と、 RegexObject のメソッドとして提供されることに注意して下さい。関数は正規表現オブジェクトのコンパイルを必要としない近道ですが、いくつかのチューニング変数を失います。
参考
正規表現 (すなわち RE) は、表現にマッチ (match) する文字列の集合を表しています。このモジュールの関数を使えば、ある文字列が指定の正規表現にマッチするか (または指定の正規表現がある文字列にマッチするか、つまりは同じことですが) を検査できます。
正規表現を連結すると新しい正規表現を作れます。 A と B がともに正規表現であれば AB も正規表現です。一般的に、文字列 p が A とマッチし、別の文字列 q が B とマッチすれば、文字列 pq は AB にマッチします。ただし、この状況が成り立つのは、 A と B との間に境界条件がある場合や、番号付けされたグループ参照のような、優先度の低い演算を A や B が含まない場合だけです。かくして、ここで述べるような、より簡単でプリミティブな正規表現から、複雑な正規表現を容易に構築できます。正規表現に関する理論と実装の詳細については上記の Friedl 本か、コンパイラの構築に関する教科書を調べて下さい。
以下で正規表現の形式に関する簡単な説明をしておきます。より詳細な情報やよりやさしい説明に関しては、 正規表現 HOWTO を参照下さい。
正規表現には、特殊文字と通常文字の両方を含められます。 'A' 、 'a' 、あるいは '0' のようなほとんどの通常文字は最も簡単な正規表現になります。こうした文字は、単純にその文字自体にマッチします。通常の文字は連結できるので、 last は文字列 'last' とマッチします。 (この節の以降の説明では、正規表現を引用符を使わずに この表示スタイル: special style で書き、マッチ対象の文字列は、 '引用符で括って' 書きます。)
'|' や '(' といったいくつかの文字は特殊文字です。特殊文字は通常の文字の種別を表したり、あるいは特殊文字の周辺にある通常の文字に対する解釈方法に影響します。正規表現パターン文字列には、 null byte を含めることができませんが、 \number 記法や、 '\x00' などとして指定することができます。
特殊文字を以下に示します:
特殊文字をエスケープする( '*' や '?' 等のような文字とのマッチをできるようにする) か、あるいは、特殊シーケンスの合図です; 特殊シーケンスは後で議論します。
もしパターンを表現するのに raw string を使用していないのであれば、 Python も、バックスラッシュを文字列リテラルでのエスケープシーケンスとして使っていることを覚えていて下さい;もしエスケープシーケンスを Python の構文解析器が認識して処理しなければ、そのバックスラッシュとそれに続く文字は、結果の文字列にそのまま含まれます。しかし、もし Python が結果のシーケンスを認識するのであれば、バックスラッシュを 2回繰り返さなければいけません。このことは複雑で理解しにくいので、最も簡単な表現以外は、すべて raw string を使うことをぜひ勧めます。
文字の集合を指定するのに使用します。文字は個々にリストするか、文字の範囲を、2つの文字と '-' でそれらを分離して指定することができます。特殊文字は集合内では有効ではありません。例えば、 [akm$] は、文字 'a' 、 'k' 、 'm' 、あるいは '$' のどれかとマッチします; [a-z] は、任意の小文字と、 [a-zA-Z0-9] は、任意の文字や数字とマッチします。 (以下で定義する) \w や \S のような文字クラスも、範囲に含めることができます。しかしながら、それら文字クラスのマッチは有効になっている LOCALE 、もしくは、 UNICODE のモードに依存します。もし文字集合に ']' や '-' を含めたいのなら、その前にバックスラッシュを付けるか、それを最初の文字として指定します。たとえば、パターン []] は ']' とマッチします。
範囲内にない文字とは、その集合の 補集合をとること でマッチすることができます。これは、集合の最初の文字として '^' を含めることで表すことができます;他の場所にある '^' は、単純に '^' 文字とマッチするだけです。例えば、 [^5] は、 '5' 以外の任意の文字とマッチし、 [^^] は、 '^' 以外の任意の文字とマッチします。
[] の中では、特殊な形式や特殊文字が、その意味を失い、ここに記述された書式だけが有効であることに注意して下さい。例えば、 +, *, (, ), などは [] の中では文字通りに扱われ、後方参照は [] の中では使用できません。
( 集合 'i', 'L', 'm', 's', 'u', 'x' から1文字以上) 。グループは空文字列ともマッチします;文字は、正規表現全体の対応するフラグ (re.I (大文字・小文字を区別しない), re.L (ロケール依存), re.M (MULTILINEモード), re.S (DOTALLモード), re.U (Unicode依存), re.X (冗長) ) を設定します。 (フラグについては、 モジュールコンテンツ に記述があります) これは、もし flag 引数を re.compile() 関数に渡さずに、そのフラグを正規表現の一部として含めたいならば役に立ちます。
(?x) フラグは、式が構文解析される方法を変更することに注意して下さい。これは式文字列内の最初か、あるいは1つ以上の空白文字の後で使うべきです。もしこのフラグの前に非空白文字があると、その結果は未定義です。
正規表現の丸括弧と同様ですが、グループによってマッチされたサブ文字列は、正規表現の残りの部分から name という記号グループ名を利用してアクセスできます。グループ名は、正しい Python 識別子でなければならず、各グループ名は、正規表現内で一度だけ定義されなければなりません。記号グループは、グループに名前が付けられていない場合のように、番号付けされたグループでもあります。そこで下の例で id という名前がついたグループは、番号グループ 1 として参照することもできます。
たとえば、もしパターンが (?P<id>[a-zA-Z_]\w*) であれば、このグループは、マッチオブジェクトのメソッドへの引数に、 m.group('id') あるいは m.end('id') のような名前で、また同じ正規表現内 (例えば、 (?P=id)) や置換テキスト内 (\g<id> のように) で名前で参照することができます。
もし文字列内の現在位置の前に、現在位置で終わる ... とのマッチがあれば、マッチします。これは 肯定後読みアサーション (positive lookbehind assertion) と呼ばれます。 (?<=abc)def は、 abcdef にマッチを見つけます、というのは後読みが3文字をバックアップして、含まれているパターンとマッチするかどうか検査するからです。含まれるパターンは、固定長の文字列にのみマッチしなければなりません、ということは、 abc や a|b は許されますが、 a* や a{3,4} は許されないことを意味します。肯定後読みアサーションで始まるパターンは、検索される文字列の先頭とは決してマッチしないことに注意して下さい;多分、 match() 関数よりは search() 関数を使いたいでしょう:
>>> import re
>>> m = re.search('(?<=abc)def', 'abcdef')
>>> m.group(0)
'def'
この例ではハイフンに続く単語を探します:
>>> m = re.search('(?<=-)\w+', 'spam-egg')
>>> m.group(0)
'egg'
グループに id が与えられている、もしくは name があるとき、 yes-pattern とマッチします。存在しないときには no-pattern とマッチします。 no-pattern はオプションで省略できます。例えば (<)?(\w+@\w+(?:\.\w+)+)(?(1)>) はemailアドレスとマッチする最低限のパターンです。これは '<user@host.com>' や 'user@host.com' にはマッチしますが、 '<user@host.com' にはマッチしません。
バージョン 2.4 で追加.
特殊シーケンスは '\' と以下のリストにある文字から構成されます。もしリストにあるのが通常文字でないならば、結果の RE は2番目の文字とマッチします。例えば、 \$ は文字 '$' とマッチします。
LOCALE と UNICODE フラグが指定されていない場合、任意の空白文字とマッチします;これは集合 [\t\n\r\f\v] と同じ意味です。
LOCALE がある場合、これはこの集合に加えて現在のロケールで空白と定義されている全てにマッチします。 UNICODE が設定されると、これは [ \t\n\r\f\v] と Unicode 文字特性データベースで空白と分類されている全てにマッチします。
Python 文字列リテラルによってサポートされている標準エスケープのほとんども、正規表現パーザに認識されます:
\a \b \f \n
\r \t \v \x
\\
8進エスケープは制限された形式で含まれています:もし第1桁が 0 であるか、もし8進3桁であれば、それは 8進エスケープとみなされます。そうでなければ、それはグループ参照です。文字列リテラルについて、 8進エスケープはほとんどの場合3桁長になります。
Python は、正規表現に基づく、2つの異なるプリミティブな操作を提供しています。 search が文字列のすべての場所で、一致するかを確認する (これは Perl のデフォルト動作です) のに対し、 match は、文字列の先頭で一致するかを確認します。
マッチは、 '^' で始まる正規表現を使ったとしても、検索と異なる動作になるかもしれないことに注意して下さい: '^' は文字列の先頭、もしくは、 MULTILINE モードでは改行の直後ともマッチします。 “マッチ” 操作は、もしそのパターンが、モードに拘らず文字列の先頭とマッチするか、あるいは改行がその前にあるかどうかに拘らず、省略可能な pos 引数によって与えられる先頭位置でマッチする場合のみ成功します。
>>> re.match("c", "abcdef") # マッチしない
>>> re.search("c", "abcdef") # マッチする
<_sre.SRE_Match object at ...>
このモジュールは幾つかの関数、定数、例外を定義します。この関数のいくつかはコンパイル済み正規表現向けの完全版のメソッドを簡略化したバージョンです。それなりのアプリケーションのほとんどで、コンパイルされた形式が用いられるのが普通です。
正規表現パターンを正規表現オブジェクトにコンパイルします。このオブジェクトは、以下で述べる match() と search() メソッドを使って、マッチングに使うことができます。
式の動作は、 flags の値を指定することで加減することができます。値は以下の変数を、ビットごとの OR ( | 演算子)を使って組み合わせることができます。
シーケンス
prog = re.compile(pattern)
result = prog.match(string)
は、
result = re.match(pattern, string)
と同じ意味ですが、 re.compile() を使ってその結果の正規表現オブジェクトを再利用した方が、その式を一つのプログラムで何回も使う時にはより効率的です。
ノート
最後に re.match(), re.search(), re.compile() に渡されたパターンのコンパイルされたものがキャッシュとして残ります。そのため、正規表現をひとつだけしか使わないプログラムは正規表現のコンパイルを気にする必要はありません。
指定されると、パターン文字 '^' は、文字列の先頭および各行の先頭(各改行の直後)とマッチします;そしてパターン文字 '$' は文字列の末尾および各行の末尾 (改行の直前) とマッチします。デフォルトでは、 '^' は、文字列の先頭とだけマッチし、 '$' は、文字列の末尾および文字列の末尾の改行の直前(がもしあれば)とマッチします。
\w 、 \W 、 \b 、 \B 、 \d 、 \D 、 \s と \S を、 Unicode 文字特性データベースに従わさせます。
バージョン 2.0 で追加.
このフラグによって、より見やすく正規表現を書くことができます。パターン内の空白は、文字クラス内にあるかエスケープされていないバックスラッシュが前にある時以外は無視されます。また、行に、文字クラス内にもなく、エスケープされていないバックスラッシュが前にもない '#' がある時は、そのような '#' の左端からその行の末尾までが無視されます。
つまり、数字にマッチする下記のふたつの正規表現オブジェクトは、機能的に等価です。:
a = re.compile(r"""\d + # 整数部
\. # 小数点
\d * # 小数点以下""", re.X)
b = re.compile(r"\d+\.\d*")
string 全体を走査して、正規表現 pattern がマッチを発生する位置を探して、対応する MatchObject インスタンスを返します。もし文字列内に、そのパターンとマッチする位置がないならば、 None を返します;これは、文字列内のある点で長さゼロのマッチを探すこととは異なることに注意して下さい。
もし string の先頭で 0 個以上の文字が正規表現 pattern とマッチすれば、対応する MatchObject インスタンスを返します。もし文字列がパターンとマッチしなければ、 None を返します;これは長さゼロのマッチとは異なることに注意して下さい。
ノート
もし string のどこかにマッチを位置付けたいのであれば、代わりに search() を使って下さい。
string を、 pattern があるたびに分割します。もし括弧のキャプチャが pattern で使われていれば、パターン内のすべてのグループのテキストも結果のリストの一部として返されます。 maxsplit がゼロでなければ、高々 maxsplit 個の分割が発生し、文字列の残りは、リストの最終要素として返されます。 (非互換性ノート:オリジナルの Python 1.5 リリースでは、 maxsplit は無視されていました。これはその後のリリースでは修正されました。)
>>> re.split('\W+', 'Words, words, words.')
['Words', 'words', 'words', '']
>>> re.split('(\W+)', 'Words, words, words.')
['Words', ', ', 'words', ', ', 'words', '.', '']
>>> re.split('\W+', 'Words, words, words.', 1)
['Words', 'words, words.']
もし、捕捉するグループが分割パターンに含まれ、それが文字列の先頭にあるならば、分割結果は、空文字列から始まります。文字列最後においても同様です。
>>> re.split('(\W+)', '...words, words...')
['', '...', 'words', ', ', 'words', '...', '']
その場合、常に、分割要素が、分割結果のリストの相対的なインデックスに現れます。 (例えば、分割子の中に捕捉するグループが一つだけあれば、0番目、2番目、そして、4番目です)
split は空のパターンマッチでは、文字列を分割しないことに注意して下さい。例えば:
>>> re.split('x*', 'foo')
['foo']
>>> re.split("(?m)^$", "foo\n\nbar\n")
['foo\n\nbar\n']
pattern の string へのマッチのうち、重複しない全てのマッチを文字列のリストとして返します。 string は左から右へと走査され、マッチは見つかった順番で返されます。パターン中に何らかのグループがある場合、グループのリストを返します。グループが複数定義されていた場合、タプルのリストになります。他のマッチの開始部分に接触しないかぎり、空のマッチも結果に含められます。
バージョン 1.5.2 で追加.
バージョン 2.4 で変更: オプションの flags 引数を追加しました.
string 内の RE pattern の重複しないマッチを MatchObject インスタンスを返す iterator を返します。 string は左から右へと走査され、マッチは見つかった順番で返されます。他のマッチの開始部分に接触しないかぎり、空のマッチも結果に含められます。
バージョン 2.2 で追加.
バージョン 2.4 で変更: Added the optional flags argument.
string 内で、 pattern と重複しないマッチの内、一番左にあるものを置換 repl で置換して得られた文字列を返します。もしパターンが見つからなければ、 string を変更せずに返します。 repl は文字列でも関数でも構いません;もしそれが文字列であれば、それにある任意のバックスラッシュエスケープは処理されます。すなわち、 \n は単一の改行文字に変換され、 \r は、行送りコードに変換されます、等々。 \j のような未知のエスケープはそのままにされます。 \6 のような後方参照(backreference)は、パターンのグループ 6 とマッチしたサブ文字列で置換されます。例えば:
>>> re.sub(r'def\s+([a-zA-Z_][a-zA-Z_0-9]*)\s* \(\s*\):',
... r'static PyObject*\npy_\1(void)\n{',
... 'def myfunc():')
'static PyObject*\npy_myfunc(void)\n{'
もし repl が関数であれば、重複しない pattern が発生するたびにその関数が呼ばれます。この関数は一つのマッチオブジェクト引数を取り、置換文字列を返します。例えば:
>>> def dashrepl(matchobj):
... if matchobj.group(0) == '-': return ' '
... else: return '-'
>>> re.sub('-{1,2}', dashrepl, 'pro----gram-files')
'pro--gram files'
パターンは、文字列でも RE でも構いません;もし正規表現フラグを指定する必要があれば、 RE オブジェクトを使うか、パターンに埋込み修飾子を使わなければなりません;たとえば、 sub("(?i)b+", "x", "bbbb BBBB") は 'x x' を返します。
省略可能な引数 count は、置換されるパターンの出現回数の最大値です; count は非負の整数でなければなりません。もし省略されるかゼロであれば、出現したものがすべて置換されます。パターンのマッチが空であれば、以前のマッチと隣合わせでない時だけ置換されますので、 sub('x*', '-', 'abc') は '-a-b-c-' を返します。
上で述べた文字エスケープや後方参照の他に、 \g<name> は、 (?P<name>...) のシンタクスで定義されているように、 name という名前のグループとマッチしたサブ文字列を使います。 \g<number> は対応するグループ番号を使います;それゆえ \g<2> は \2 と同じ意味ですが、 \g<2>0 のような置換でもあいまいではありません。 \20 は、グループ 20 への参照として解釈されますが、グループ 2 にリテラル文字 '0' が続いたものへの参照としては解釈されません。後方参照 \g<0> は、 RE とマッチするサブ文字列全体を置き換えます。
sub() と同じ操作を行いますが、タプル (new_string、 number_of_subs_made) を返します。
バックスラッシュにすべての非英数字をつけた string を返します;これはもし、その中に正規表現のメタ文字を持つかもしれない任意のリテラル文字列とマッチしたいとき、役に立ちます。
正規表現キャッシュをクリアします。
ここでの関数の一つに渡された文字列が、正しい正規表現ではない時 (例えば、その括弧が対になっていなかった)、あるいはコンパイルやマッチングの間になんらかのエラーが発生したとき、発生する例外です。たとえ文字列がパターンとマッチしなくても、決してエラーではありません。
RegexObject クラスは以下のメソッドと属性をサポートします:
string を走査して、この正規表現がマッチする場所を探し、対応する MatchObject インスタンスを返します。 string のどこにもマッチしない場合は None を返します。これは、 string 内のどこかで長さ0でマッチした場合と異なることに注意してください。
省略可能な、2つ目の引数 pos は、 string のどこから探し始めるかを指定する index で、デフォルトでは 0 です。これは、文字列をスライスしてから検索するのと、完全には同じではありません。パターン文字 '^' は本当の文字列の先頭と、改行の直後にマッチしますが、検索を開始する index がマッチするとは限りません。
省略可能な引数 endpos は string のどこまでを検索するかを制限します。これは string の長さが endpos 文字だった場合と同じように動作します。つまり、 pos から endpos - 1 の範囲の文字に対してパターンマッチします。 endpos が pos よりも小さい場合は、マッチは見つかりません。それ以外の場合は、 rx がコンパイルされた正規表現として、 rx.search(string, 0, 50) は rx.search(string[:50], 0) と同じです。
>>> pattern = re.compile("d")
>>> pattern.search("dog") # Match at index 0
<_sre.SRE_Match object at ...>
>>> pattern.search("dog", 1) # No match; search doesn't include the "d"
もし string の 先頭の 0 個以上の文字がこの正規表現とマッチすれば、対応する MatchObject インスタンスを返します。もし文字列がパタンーとマッチしなければ、 None を返します。これは長さゼロのマッチとは異なることに注意して下さい。
省略可能な引数 pos と endpos 引数は、 search() メソッドと同じ意味を持ちます。
ノート
string のどこにでもマッチさせたければ、代わりに search() を使って下さい。
>>> pattern = re.compile("o")
>>> pattern.match("dog") # "o" は文字列 "dog." の先頭にないため、マッチしません
>>> pattern.match("dog", 1) # "o" が文字列 "dog" の2番目にあるので、マッチします
<_sre.SRE_Match object at ...>
split() 関数と同様で、コンパイルしたパターンを使います。ただし、 match() と同じように、省略可能な pos, endpos 引数で検索範囲を指定することができます。
findall() 関数と同様で、コンパイルしたパターンを使います。ただし、 match() と同じように、省略可能な pos, endpos 引数で検索範囲を指定することができます。
finditer() 関数と同様で、コンパイルしたパターンを使います。ただし、 match() と同じように、省略可能な pos, endpos 引数で検索範囲を指定することができます。
RE オブジェクトがコンパイルされたとき使われた flags 引数です。もし flags が何も提供されなければ 0 です。
パターンにあるキャプチャグループの数です。
(?P<id>) で定義された任意の記号グループ名の、グループ番号への辞書マッピングです。もし記号グループがパターン内で何も使われていなければ、辞書は空です。
RE オブジェクトがそれからコンパイルされたパターン文字列です。
MatchObject は、常に真偽値 True を持ちます。そのため、例えば match() がマッチしたかどうかを単純な if 文で確認することができます。 MatchObject は以下のメソッドと、属性を持ちます。
テンプレート文字列 template に、 sub() メソッドがするようなバックスラッシュ置換をして得られる文字列を返します。 \n のようなエスケープは適当な文字に変換され、数値の後方参照 (\1, \2) と名前付きの後方参照 (\g<1>, \g<name>) は、対応するグループの内容で置き換えられます。
マッチした1個以上のサブグループを返します。もし引数で一つであれば、その結果は一つの文字列です。複数の引数があれば、その結果は、引数ごとに一項目を持つタプルです。引数がなければ、 group1 はデフォールトでゼロです(マッチしたものすべてが返されます)。もし groupN 引数がゼロであれば、対応する戻り値は、マッチする文字列全体です。もしそれが範囲 [1..99] 内であれば、それは、対応する丸括弧つきグループとマッチする文字列です。もしグループ番号が負であるか、あるいはパターンで定義されたグループの数より大きければ、 IndexError 例外が発生します。グループがマッチしなかったパターンの一部に含まれていれば、対応する結果は None です。グループが、複数回マッチしたパターンの一部に含まれていれば、最後のマッチが返されます。
>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
>>> m.group(0) # マッチした全体
'Isaac Newton'
>>> m.group(1) # ひとつめのパターン化されたサブグループ
'Isaac'
>>> m.group(2) # ふたつめのパターン化されたサブグループ
'Newton'
>>> m.group(1, 2) # 複数の引数を与えるとタプルが返る
('Isaac', 'Newton')
もし正規表現が (?P<name>...) シンタックスを使うならば、 groupN 引数は、それらのグループ名によってグループを識別する文字列であっても構いません。もし文字列引数がパターンのグループ名として使われていないものであれば、 IndexError 例外が発生します。
適度に複雑な例題:
>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcom Reynolds")
>>> m.group('first_name')
'Malcom'
>>> m.group('last_name')
'Reynolds'
名前の付けられたグループは、そのインデックスによっても参照できます。
>>> m.group(1)
'Malcom'
>>> m.group(2)
'Reynolds'
もし、グループが複数回マッチする場合、最後のマッチだけが利用可能となります。
>>> m = re.match(r"(..)+", "a1b2c3") # 3回マッチする
>>> m.group(1) # 最後のマッチだけが返る
'c3'
マッチの、1からパターン内にある全グループ数までのすべてのサブグループを含むタプルを返します。 default 引数は、マッチに加わらなかったグループ用に使われ、デフォールトでは None です。 (非互換性ノート:オリジナルの Python 1.5 リリースでは、たとえタプルが一要素長であっても、その代わりに文字列を返していました。 (1.5.1 以降の)後のバージョンでは、そのような場合には、要素がひとつのタプルが返されます。)
例えば:
>>> m = re.match(r"(\d+)\.(\d+)", "24.1632")
>>> m.groups()
('24', '1632')
もし、整数部にのみ着目し、あとの部分をオプションとした場合、マッチの中に現れないグループがあるかも知れません。それらのグループは、 default 引数が与えられていない場合、デフォルトでは None になります。
>>> m = re.match(r"(\d+)\.?(\d+)?", "24")
>>> m.groups() # ふたつめのグループはデフォルトでは None になる
('24', None)
>>> m.groups('0') # この場合、ふたつめのグループのデフォルトは 0 になる
('24', '0')
マッチの、すべての 名前つきの サブグループを含む、サブグループ名でキー付けされた辞書を返します。 default 引数はマッチに加わらなかったグループに使われ、デフォールトでは None です。例えば、
>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcom Reynolds")
>>> m.groupdict()
{'first_name': 'Malcom', 'last_name': 'Reynolds'}
group とマッチした部分文字列の先頭と末尾のインデックスを返します。 group は、デフォルトでは(マッチした部分文字列全体を意味する)ゼロです。 group が存在してもマッチに寄与しなかった場合は、 -1 を返します。マッチオブジェクト m および、マッチに寄与しなかったグループ g があって、グループ g とマッチしたサブ文字列 ( m.group(g) と同じ意味ですが ) は:
m.string[m.start(g):m.end(g)]
です。もし group が空文字列とマッチすれば、 m.start(group) が m.end(group) と等しくなることに注意して下さい。例えば、 m = re.search('b(c?)', 'cba') とすると、 m.start(0) は 1 で、 m.end(0) は 2 であり、 m.start(1) と m.end(1) はともに 2 であり、 m.start(2) は IndexError 例外を発生します。
例として、電子メールのアドレスから remove_this を取り除く場合を示します。
>>> email = "tony@tiremove_thisger.net"
>>> m = re.search("remove_this", email)
>>> email[:m.start()] + email[m.end():]
'tony@tiger.net'
MatchObject m について、大きさ2のタプル (m.start(group), m.end(group)) を返します。もし group がマッチに寄与しなかったら、これは (-1, -1) です。また group はデフォルトでゼロです。
RegexObject の search() か match() に渡された pos の値です。これは RE エンジンがマッチを探し始める位置の文字列のインデックスです。
RegexObject の search() か match() に渡された endpos の値です。これは RE エンジンがそれ以上は進まない位置の文字列のインデックスです。
最後にマッチした取り込みグループの整数インデックスです。もしどのグループも全くマッチしなければ None です。例えば、 (a)b, ((a)(b)) や ((ab)) といった表現が 'ab' に適用された場合、 lastindex == 1 となり、同じ文字列に (a)(b) が適用された場合には lastindex == 2 となるでしょう。
最後にマッチした取り込みグループの名前です。もしグループに名前がないか、あるいはどのグループも全くマッチしなければ None です。
この MatchObject インスタンスを match() あるいは search() メソッドで生成した正規表現オブジェクトです。
この例では、マッチオブジェクトの表示を少し美しくするために、下記の補助関数を使用します :
def displaymatch(match):
if match is None:
return None
return '<Match: %r, groups=%r>' % (match.group(), match.groups())
あなたがポーカープログラムを書いているとします。プレイヤーの持ち札はそれぞれの文字が1枚のカードを意味する5文字の文字列によって表現されます。 “a” はエース、 “k” はキング、 “q” はクイーン、 “j” はジャック “0” は10、そして “1” から “9” はそれぞれの数字のカードを表します。
与えられた文字列が、持ち札として有効かを確認するために、下記のようにするかも知れません。 :
>>> valid = re.compile(r"[0-9akqj]{5}$")
>>> displaymatch(valid.match("ak05q")) # Valid.
"<Match: 'ak05q', groups=()>"
>>> displaymatch(valid.match("ak05e")) # Invalid.
>>> displaymatch(valid.match("ak0")) # Invalid.
>>> displaymatch(valid.match("727ak")) # Valid.
"<Match: '727ak', groups=()>"
最後の持ち札 "727ak" は、ペアを含んでいます。言い換えると同じ値のカードが2枚あります。これを正規表現にマッチさせるために、後方参照を使う場合もあります :
>>> pair = re.compile(r".*(.).* \1")
>>> displaymatch(pair.match("717ak")) # 7 のペア
"<Match: '717', groups=('7',)>"
>>> displaymatch(pair.match("718ak")) # ペア無し
>>> displaymatch(pair.match("354aa")) # エースのペア
"<Match: '354aa', groups=('a',)>"
どのカードのペアになっているかを調べるため、下記のように MatchObject の group() メソッドを使う場合があります。
>>> pair.match("717ak").group(1)
'7'
# re.match() が group() メソッドを持たない None を返すため、エラーとなる :
>>> pair.match("718ak").group(1)
Traceback (most recent call last):
File "<pyshell#23>", line 1, in <module>
re.match(r".*(.).* \1", "718ak").group(1)
AttributeError: 'NoneType' object has no attribute 'group'
>>> pair.match("354aa").group(1)
'a'
Python には現在のところ、 scanf() に相当するものがありません。正規表現は、 scanf() のフォーマット文字列よりも、一般的により強力であり、また冗長でもあります。以下の表に、 scanf() のフォーマットトークンと正規表現の大体同等な対応付けを示します。
scanf() トークン | 正規表現 |
---|---|
%c | . |
%5c | .{5} |
%d | [-+]?\d+ |
%e, %E, %f, %g | [-+]?(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)? |
%i | [-+]?(0[xX][\dA-Fa-f]+|0[0-7]*|\d+) |
%o | 0[0-7]* |
%s | \S+ |
%u | \d+ |
%x, %X | 0[xX][\dA-Fa-f]+ |
/usr/sbin/sendmail - 0 errors, 4 warnings
のような文字列からファイル名と数値を抽出するには、
%s - %d errors, %d warnings
のように scanf() フォーマットを使うでしょう。それと同等な正規表現は
(\S+) - (\d+) errors, (\d+) warnings
エンジンに大量の再帰を要求するような正規表現を作成すると、 maximum recursion limit exceeded (最大再帰制限を超過した) というメッセージを持つ RuntimeError 例外に出くわすかもしれません。たとえば、
>>> s = "Begin" + 1000 * 'a very long string' + 'end'
>>> re.match('Begin (\w| )*? end', s).end()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "/usr/local/lib/python2.5/re.py", line 132, in match
return _compile(pattern, flags).match(string)
RuntimeError: maximum recursion limit exceeded
再帰を避けるように正規表現を組みなおせることはよくあります。
Python 2.3 からは、再帰を避けるために *? パターンの利用が特別扱いされるようになりました。したがって、上の正規表現は Begin[a-zA-Z0-9_ ]*?end に書き直すことで再帰を防ぐことができます。それ以上の恩恵として、そのような正規表現は、再帰的な同等のものよりもより速く動作します。
簡単に言えば、 match() は文字列の先頭でのみパターンにマッチしようとします。対して、 search() は文字列のどこででもパターンにマッチしようとします。例えば :
>>> re.match("o", "dog") # "o" は文字列 "dog" の最初の文字ではないのでマッチしません
>>> re.search("o", "dog") # search() では、文字列のどこであってもマッチする
<_sre.SRE_Match object at ...>
ノート
以下は、 re.compile("pattern") により生成された正規表現オブジェクトにのみ当てはまります。 re.match(pattern, string) や re.search(pattern, string) などには当てはまりません。
match() は、検索開始インデックスを指定するための、オプショナルな2つめのパラメータをとります。
>>> pattern = re.compile("o")
>>> pattern.match("dog") # "o" が "dog" の先頭にないのでマッチしない
# 検索開始インデックスのデフォルト値が 0 であるため上記と等価 :
>>> pattern.match("dog", 0)
# "o" が "dog" の2番目の文字なのでマッチする ( インデックス 0 が最初の文字である ) :
>>> pattern.match("dog", 1)
<_sre.SRE_Match object at ...>
>>> pattern.match("dog", 2) # "o" は "dog" の3番目の文字ではないのでマッチしない
split() は文字列を与えられたパターンで分割し、リストにして返します。下記の、電話帳作成の例のように、このメソッドはテキストデータを読みやすくしたり、 Python で編集したりしやすくする際に、非常に役に立ちます。
最初に、入力を示します。通常、これはファイルからの入力になるでしょう。ここでは、3重引用符の書式とします :
>>> input = """Ross McFluff: 834.345.1254 155 Elm Street
...
... Ronald Heathmore: 892.345.3428 436 Finley Avenue
... Frank Burger: 925.541.7625 662 South Dogwood Way
...
...
... Heather Albrecht: 548.326.4584 919 Park Place"""
個々の記録は、1つ以上の改行で区切られています。まずは、文字列から空行を除き、記録ごとのリストに変換しましょう。
>>> entries = re.split("\n+", input)
>>> entries
['Ross McFluff: 834.345.1254 155 Elm Street',
'Ronald Heathmore: 892.345.3428 436 Finley Avenue',
'Frank Burger: 925.541.7625 662 South Dogwood Way',
'Heather Albrecht: 548.326.4584 919 Park Place']
そして、各記録を、名、姓、電話番号、そして、住所に分割してリストにします。分割のためのパターンに使っている空白文字が、住所には含まれるため、 split() の maxsplit 引数を使います。 :
>>> [re.split(":? ", entry, 3) for entry in entries]
[['Ross', 'McFluff', '834.345.1254', '155 Elm Street'],
['Ronald', 'Heathmore', '892.345.3428', '436 Finley Avenue'],
['Frank', 'Burger', '925.541.7625', '662 South Dogwood Way'],
['Heather', 'Albrecht', '548.326.4584', '919 Park Place']]
パターン、 :? は姓に続くコロンにマッチします。そのため、コロンは分割結果のリストには現れません。 maxsplit を 4 にすれば、ハウスナンバーと、ストリート名を分割することができます。 :
>>> [re.split(":? ", entry, 4) for entry in entries]
[['Ross', 'McFluff', '834.345.1254', '155', 'Elm Street'],
['Ronald', 'Heathmore', '892.345.3428', '436', 'Finley Avenue'],
['Frank', 'Burger', '925.541.7625', '662', 'South Dogwood Way'],
['Heather', 'Albrecht', '548.326.4584', '919', 'Park Place']]
sub() はパターンにマッチした部分を文字列や関数の返り値で置き換えます。この例では、”秘匿” する文字列に、関数と共に sub() を適用する例を示します。言い換えると、最初と最後の文字を除く、単語中の文字の位置をランダム化します。
>>> def repl(m):
... inner_word = list(m.group(2))
... random.shuffle(inner_word)
... return m.group(1) + "".join(inner_word) + m.group(3)
>>> text = "Professor Abdolmalek, please report your absences promptly."
>>> re.sub(r"(\w)(\w+)(\w)", repl, text)
'Poefsrosr Aealmlobdk, pslaee reorpt your abnseces plmrptoy.'
>>> re.sub(r"(\w)(\w+)(\w)", repl, text)
'Pofsroser Aodlambelk, plasee reoprt yuor asnebces potlmrpy.'
findall() はパターンにマッチする 全てに マッチします。 search() がそうであるように、最初のものだけに、ではありません。例えば、なにかの文章の全ての副詞を見つけたいとき、下記のように findall() を使います。 :
>>> text = "He was carefully disguised but captured quickly by police."
>>> re.findall(r"\w+ly", text)
['carefully', 'quickly']
もし、パターンにマッチするものについて、マッチしたテキスト以上の情報を得たいと考えたとき、文字列ではなく MatchObject のインスタンスを返す finditer() が便利です。以下に例を示すように、なにかの文章の全ての副詞と、 その位置を 調べたいと考えたとき、下記のように finditer() を使います。 :
>>> text = "He was carefully disguised but captured quickly by police."
>>> for m in re.finditer(r"\w+ly", text):
... print '%02d-%02d: %s' % (m.start(), m.end(), m.group(0))
07-16: carefully
40-47: quickly
Raw string記法 (r"text") により、バックスラッシュ ('\') を個々にバックスラッシュでエスケープすることなしに、正規表現を正常な状態に保ちます。例えば、下記の2つのコードは機能的に等価です。 :
>>> re.match(r"\W(.)\1\W", " ff ")
<_sre.SRE_Match object at ...>
>>> re.match("\\W(.)\\1\\W", " ff ")
<_sre.SRE_Match object at ...>
文字通りのバックスラッシュにマッチさせたいなら、正規表現中ではエスケープする必要があります。 Raw string記法では、 r"\\" ということになります。 Raw string記法を用いない場合、 "\\\\" としなくてはなりません。下記のコードは機能的に等価です。 :
>>> re.match(r"\\", r"\\")
<_sre.SRE_Match object at ...>
>>> re.match("\\\\", r"\\")
<_sre.SRE_Match object at ...>