"re" --- 正規表現操作
*********************

**ソースコード:** Lib/re/

======================================================================

このモジュールは Perl に見られる正規表現マッチング操作と同様のものを提
供します。

パターンおよび検索される文字列には、Unicode 文字列 ("str") や 8 ビット
文字列 ("bytes") を使います。ただし、Unicode 文字列と 8 ビット文字列の
混在はできません。つまり、Unicode 文字列にバイト列のパターンでマッチン
グしたり、その逆はできません。同様に、置換時の置換文字列はパターンおよ
び検索文字列の両方と同じ型でなくてはなりません。

正規表現では、特殊な形式を表すためや、特殊文字をその特殊な意味を発動さ
せず使うために、バックスラッシュ文字 ("'\'") を使います。こうしたバッ
クスラッシュの使い方は、 Python の文字列リテラルにおける同じ文字の使い
方と衝突します。例えば、リテラルのバックスラッシュにマッチさせるには、
パターン文字列として "'\\\\'" と書かなければなりません。なぜなら、正規
表現は "\\" でなければならないうえ、それぞれのバックスラッシュは標準の
Python 文字列リテラルで "\\" と表現せねばならないからです。 Python の
文字列リテラルにおいて、バックスラッシュの使用による不正なエスケープ文
字がある場合は、"SyntaxWarning" が発生し、将来的には "SyntaxError" に
なることにも注意してください。この動作は、正規表現として有効な文字列に
対しても同様です。

これを解決するには、正規表現パターンに Python の raw 文字列記法を使い
ます。 "'r'" を前置した文字列リテラル内ではバックスラッシュが特別扱い
されません。従って ""\n"" が改行一文字からなる文字列であるのに対して、
"r"\n"" は "'\'" と "'n'" の二文字からなる文字列です。通常、 Python コ
ード中では、パターンをこの raw 文字列記法を使って表現します。

重要なこととして、大抵の正規表現操作は、モジュールレベルの関数としても
、 コンパイル済み正規表現 のメソッドとしても利用できます。関数は正規表
現オブジェクトを前もってコンパイルする必要がない近道ですが、微調整のた
めの変数が減ります。

参考:

  サードパーティーの regex モジュールは、標準ライブラリの "re" モジュ
  ールと互換性のある API に加え、追加の機能とより充実した Unicode サポ
  ートを提供します。


正規表現の構文
==============

正規表現 (または RE) は、その表現にマッチ (match) する文字列の集合を指
定します。このモジュールの関数を使えば、ある文字列が与えられた正規表現
にマッチするか (または、与えられた正規表現がある文字列にマッチするか、
と言い換えても同じことになります) を検査できます。

正規表現を連結することで新しい正規表現を作れます。*A* と *B* がともに
正規表現であれば *AB* も正規表現です。一般的に、ある文字列 *p* が *A*
にマッチし、別の文字列 *q* が *B* にマッチするなら、文字列 *pq* は AB
にマッチします。ただし、 *A* または *B* に優先度の低い演算が含まれる場
合や、 *A* と *B* との間に境界条件がある場合や、番号付けされたグループ
参照をしている場合、を除きます。こうして、ここで述べるような簡単な基本
表現から、複雑な表現を容易に構築できます。正規表現に関する理論と実装の
詳細については Friedl 本 [Frie09] か、コンパイラの構築に関するテキスト
を参照してください。

以下で正規表現の形式を簡単に説明します。詳細な情報ややさしい説明は、
正規表現 HOWTO を参照してください。

正規表現には、特殊文字と通常文字の両方を含められます。 "'A'" 、 "'a'"
、または "'0'" のようなほとんどの通常文字は、最も単純な正規表現です。
これは単純に、その文字自体にマッチします。通常文字は連結できるので、
"last" は文字列 "'last'" にマッチします。 (この節では以降、正規表現は
一般にクオートを使わず "この特殊スタイルで" 表記し、マッチ対象の文字列
は、 "'シングルクオートで括って'" 表記します。)

"'|'" や "'('" など、一部の文字は特殊文字です。 特殊文字は通常文字のク
ラスを表したり、周囲の正規表現の解釈方法に影響したりします。

繰り返しの演算子または修飾子 ("*"、 "+"、 "?"、 "{m,n}" など) は直接入
れ子にはできません。これは、非貪欲な修飾子の接尾辞 "?" や他の実装での
他の修飾子との曖昧さを回避します。内側で繰り返したものをさらに繰り返す
には、丸括弧が使えます。例えば、正規表現 "(?:a{6})*" は 6 の倍数個の
"'a'" 文字にマッチします。


特殊文字
--------

特殊文字を以下に示します:


"."
~~~

(ドット) デフォルトのモードでは改行以外の任意の文字にマッチします。
"DOTALL" フラグが指定されていれば改行も含む全ての文字にマッチします。
"(?s:.)" はフラグにかかわらず全ての文字にマッチします。


"^"
~~~

(キャレット) 文字列の先頭にマッチし、 "MULTILINE" モードでは各改行の直
後にもマッチします。


"$"
~~~

文字列の末尾、あるいは文字列の末尾の改行の直前にマッチし、 "MULTILINE"
モードでは改行の前にもマッチします。 "foo" は 'foo' と 'foobar' の両方
にマッチしますが、正規表現 "foo$" は 'foo' だけにマッチします。興味深
いことに、 "'foo1\nfoo2\n'" を "foo.$" で検索した場合、通常は 'foo2'
だけにマッチしますが、 "MULTILINE" モードでは 'foo1' にもマッチします
。 "$" だけで "'foo\n'" を検索した場合、2 つの (空の) マッチを見つけま
す: 1つは改行の直前で、もう1つは文字列の末尾です。


"*"
~~~

直前の正規表現を 0 回以上、できるだけ多く繰り返したものにマッチさせる
結果の正規表現にします。例えば "ab*" は 'a'、'ab'、または 'a' に任意個
数の 'b' を続けたものにマッチします。


"+"
~~~

直前の正規表現を 1 回以上繰り返したものにマッチさせる結果の正規表現に
します。例えば "ab+" は 'a' に 1 つ以上の 'b' が続いたものにマッチし、
単なる 'a' にはマッチしません。


"?"
~~~

直前の正規表現を 0 回か 1 回繰り返したものにマッチさせる結果の正規表現
にします。例えば "ab?" は 'a' あるいは 'ab' にマッチします。


"*?", "+?", "??"
~~~~~~~~~~~~~~~~

"'*'" 、 "'+'" 、および "'?'" 修飾子は全て *貪欲 (greedy)* マッチで、
できるだけ多くのテキストにマッチします。この挙動が望ましくない時もあり
ます。例えば正規表現 "<.*>" が "'<a> b <c>'" に対してマッチされると、
"'<a>'" だけでなく文字列全体にマッチしてしまいます。修飾子の後に "?"
を追加すると、 *非貪欲 (non-greedy)* あるいは *最小 (minimal)* のマッ
チが行われ、できるだけ *少ない* 文字にマッチします。正規表現 "<.*?>"
を使うと "'<a>'" だけにマッチします。


"*+", "++", "?+"
~~~~~~~~~~~~~~~~

"'*'"、"'+'"、"'?'" の数量詞と同様に、"'+'" を後ろに付けたものも可能な
限り多くの繰り返しにマッチします。 ただし、通常の貪欲な数量詞とは異な
り、後続の式がマッチしない場合にバックトラックしません。 これらは *所
有型 (possessive)* の数量詞と呼ばれます。 例えば "a*a" は "'aaaa'" に
マッチします。 最初に "a*" が 4 個の "'a'" すべてにマッチしますが、末
尾の "'a'" に達するとバックトラックし、最終的には "a*" が 3 個の "'a'"
にマッチし、4 個目は末尾の "'a'" にマッチします。 一方、"a*+a" で
"'aaaa'" にマッチさせようとすると、"a*+" が 4 個の "'a'" すべてにマッ
チした後、末尾の "'a'" がマッチする文字は残っていません。 バックトラッ
クできないため、マッチは失敗します。 "x*+"、"x++"、"x?+" は、それぞれ
"(?>x*)"、"(?>x+)"、"(?>x?)" と等価です。

Added in version 3.11.


"{m}"
~~~~~

直前の正規表現をちょうど *m* 回繰り返したものにマッチさせるよう指定し
ます。それより少ないマッチでは正規表現全体がマッチしません。例えば、
"a{6}" は 6 個ちょうどの "'a'" 文字にマッチしますが、 5 個ではマッチし
ません。


"{m,n}"
~~~~~~~

直前の正規表現を *m* 回から *n* 回、できるだけ多く繰り返したものにマッ
チさせる結果の正規表現にします。例えば、"a{3,5}" は、3 個から 5 個の
"'a'" 文字にマッチします。*m* を省略すると下限は 0 に指定され、*n* を
省略すると上限は無限に指定されます。例として、 "a{4,}b" は "'aaaab'"
や、1,000 個の "'a'" 文字に "'b'" が続いたものにマッチしますが、
"'aaab'" にはマッチしません。コンマは省略できません、省略すると修飾子
が上で述べた形式と混同されてしまうからです。


"{m,n}?"
~~~~~~~~

結果の正規表現は、前にある正規表現を、*m* 回から *n* 回まで繰り返した
ものにマッチし、できるだけ *少なく* 繰り返したものにマッチするようにし
ます。これは、前の数量詞の非貪欲版です。例えば、 6 文字文字列
"'aaaaaa'" では、 "a{3,5}" は、5 個の "'a'" 文字にマッチしますが、
"a{3,5}?" は 3 個の文字にマッチするだけです。


"{m,n}+"
~~~~~~~~

直前の正規表現を *m* 回から *n* 回まで繰り返したものにマッチさせます。
バックトラックする位置を記録 *せずに*、できるだけ多くの繰り返しにマッ
チさせようとします。 これは前述の数量詞の所有型です。 例えば 6 文字の
文字列 "'aaaaaa'" に対し、"a{3,5}+aa" は 5 個の "'a'" にマッチした後、
さらに 2 個の "'a'" を必要とするため、文字が足りず失敗します。 一方
"a{3,5}aa" では、"a{3,5}" が最初に 5 個の "'a'" を取り込んでからバック
トラックして 4 個に減らし、残りの 2 個にパターン末尾の "aa" がマッチし
ます。 "x{m,n}+" は "(?>x{m,n})" と等価です。

Added in version 3.11.


"\"
~~~

特殊文字をエスケープ ( "'*'" や "'?'" などの文字にマッチできるようにす
る) し、または特殊シーケンスを合図します。特殊シーケンスは後で議論しま
す。

パターンを表現するのに raw 文字列を使っていないのであれば、 Python も
もまた、バックスラッシュを文字列リテラルでエスケープシーケンスとして使
うことを思い出して下さい。そのエスケープシーケンスを Python のパーザが
認識しないなら、そのバックスラッシュとそれに続く文字が結果の文字列に含
まれます。しかし、Python が結果のシーケンスを認識するなら、そのバック
スラッシュは 2 回繰り返さなければいけません。これは複雑で理解しにくい
ので、ごく単純な表現以外は、全て raw 文字列を使うことを強く推奨します
。


"[]"
~~~~

文字の集合を指定するのに使います。集合の中では:

* 文字を個別に指定できます。 "[amk]" は "'a'" 、 "'m'" または "'k'" に
  マッチします。

* 連続した文字の範囲を、 "'-'" を2 つの文字で挟んで指定できます。例え
  ば、 "[a-z]" はあらゆる小文字の ASCII 文字にマッチします。
  "[0-5][0-9]" は "00" から "59" まで全ての 2 桁の数字にマッチします。
  "[0-9A-Fa-f]" は任意の 16 進数字にマッチします。"-" がエスケープされ
  ているか (例: "[a\-z]")、先頭や末尾の文字にされていると (例: "[-a]"
  や "[a-]")、リテラル "'-'" にマッチします。

* 集合の中では、バックスラッシュ以外の特殊文字は特別な意味を失います。
  例えば "[(+*)]" は、リテラル文字 "'('"、"'+'"、"'*'"、"')'" のいずれ
  かにマッチします。

* バックスラッシュは、集合の中で特別な意味を持つ "'-'"、"']'"、"'^'"、
  "'\\'" 自体などをエスケープするか、特殊シーケンスの開始を示します。
  特殊シーケンスには、"\xa0" や "\n" のように単一の文字を表すものと、
  "\w" や "\S" のように文字クラスを表すものがあります (後述)。 "\b" は
  集合の外での単語境界ではなく、単一のバックスペース文字を表します。
  また、"\1" などの数値エスケープは常に 8 進エスケープであり、グループ
  参照ではありません。 "\A" や "\z" のように単一の文字にマッチしない特
  殊シーケンスは使えません。

* *補集合* をとって範囲内にない文字にマッチできます。集合の最初の文字
  が "'^'" なら、集合に *含まれない* 全ての文字にマッチします。例えば
  、 "[^5]" は "'5'" を除くあらゆる文字にマッチし、 "[^^]" は "'^'" を
  除くあらゆる文字にマッチします。 "^" は集合の最初の文字でなければ特
  別の意味を持ちません。

* 集合の中でリテラル "']'" にマッチさせるには、その前にバックスラッシ
  ュをつけるか、集合の先頭に置きます。例えば、 "[()[\]{}]" と
  "[]()[{}]" はどちらも閉じ角括弧、開き角括弧、波括弧、丸括弧にマッチ
  します。

* Unicode Technical Standard #18 にあるような集合の入れ子や集合操作が
  将来追加される可能性があります。これは構文を変化させるもので、この変
  化を容易にするために、さしあたって曖昧な事例には "FutureWarning" が
  送出されます。これはリテラル "'['" で始まる集合や、リテラル文字の連
  続 "'--'" 、 "'&&'" 、 "'~~'" および "'||'" を含む集合を含みます。警
  告を避けるにはバックスラッシュでエスケープしてください。

バージョン 3.7 で変更: 文字セットが将来意味論的に変化する構造を含むな
ら "FutureWarning" が送出されます。


"|"
~~~

*A* と *B* を任意の正規表現として、 "A|B" は *A* と *B* のいずれかにマ
ッチする正規表現を作成します。この方法で任意の数の正規表現を "'|'" で
分離できます。これはグループ (下記参照) 中でも使えます。対象文字列を走
査するとき、"'|'" で分離された正規表現は左から右へ順に試されます。一つ
のパターンが完全にマッチしたとき、そのパターン枝が受理されます。つまり
、ひとたび *A* がマッチしてしまえば、例え *B* によって全体のマッチが長
くなるとしても、 *B* はもはや走査されません。言いかえると、 "'|'" 演算
子は決して貪欲にはなりません。リテラル "'|'" にマッチするには、 "\|"
を使うか、 "[|]" のように文字クラス中に囲みます。


"(...)"
~~~~~~~

丸括弧で囲まれた正規表現にマッチするとともに、グループの開始と終了を表
します。グループの中身は以下で述べるように、マッチが実行された後で回収
したり、その文字列中で以降 "\number" 特殊シーケンスでマッチしたりでき
ます。リテラル "'('" や "')'" にマッチするには、"\(" や "\)" を使うか
、文字クラス中に囲みます:  "[(]"、 "[)]" 。


"(?...)"
~~~~~~~~

これは拡張記法です ("'('" の後の "'?'" は、拡張記法以外では意味を持ち
ません)。 "'?'" の直後の文字が、その構造の意味と残りの構文を決めます。
通常、拡張は新しいグループを作りません。 この規則の唯一の例外は
"(?P<name>...)" です。 現在サポートされている拡張は次のとおりです。


"(?aiLmsux)"
~~~~~~~~~~~~

("'a'"、"'i'"、"'L'"、"'m'"、"'s'"、"'u'"、"'x'" のうち 1 文字以上。)
このグループは空文字列にマッチし、各文字は正規表現全体に対応するフラグ
を設定します。

* "re.A" (ASCIIのみにマッチ)

* "re.I" (大文字小文字を無視)

* "re.L" (ロケール依存)

* "re.M" (マルチライン)

* "re.S" (ドットはすべてにマッチ)

* "re.U" (Unicodeマッチ)

* "re.X" (冗長)

(フラグについては モジュールの内容 で説明しています。) "re.compile()"
関数に *フラグ* を引数として渡す代わりに、正規表現の一部としてフラグを
含めたい場合に便利です。 フラグは正規表現文字列の先頭で使ってください
。

バージョン 3.11 で変更: この構文は正規表現の先頭でのみ使えます。


"(?:...)"
~~~~~~~~~

普通の丸括弧の、キャプチャしない版です。丸括弧で囲まれた正規表現にマッ
チしますが、このグループがマッチした部分文字列は、マッチを実行したあと
で回収することも、そのパターン中で以降参照することも *できません* 。


"(?aiLmsux-imsx:...)"
~~~~~~~~~~~~~~~~~~~~~

("'a'"、"'i'"、"'L'"、"'m'"、"'s'"、"'u'"、"'x'" のうち 0 文字以上。
その後に、"'-'" と "'i'"、"'m'"、"'s'"、"'x'" のうち 1 文字以上を続け
ることもできます。) 各文字は、正規表現のこの部分に対応するフラグを設定
または解除します。

* "re.A" (ASCIIのみにマッチ)

* "re.I" (大文字小文字を無視)

* "re.L" (ロケール依存)

* "re.M" (マルチライン)

* "re.S" (ドットはすべてにマッチ)

* "re.U" (Unicodeマッチ)

* "re.X" (冗長)

(フラグについては モジュールの内容 で説明しています。)

文字 "'a'" 、 "'L'" および "'u'" は相互に排他であり、組み合わせること
も "'-'" に続けることもできません。その代わり、これらの内一つがインラ
イングループ中に現れると、外側のグループでのマッチングモードを上書きし
ます。 Unicode パターン中では "(?a:...)" は ASCII 限定マッチングに切り
替え、 "(?u:...)" は Unicode マッチング (デフォルト) に切り替えます。
バイト列パターン中では、 "(?L:...)" はロケール依存マッチングに切り替え
、 "(?a:...)" は ASCII 限定マッチング (デフォルト) に切り替えます。こ
の上書きは狭いインライングループにのみ影響し、元のマッチングモードはグ
ループ外では復元されます。

Added in version 3.6.

バージョン 3.7 で変更: 文字 "'a'" 、 "'L'" および "'u'" もグループ中で
使えます。


"(?>...)"
~~~~~~~~~

"..." を独立した正規表現のようにマッチさせようとし、成功すると後続のパ
ターンのマッチを続けます。 後続のパターンがマッチしない場合、スタック
を巻き戻せるのは "(?>...)" より *前* の位置だけです。 *アトミックグル
ープ (atomic group)* と呼ばれるこの式は、抜けるときに内部のスタック上
の位置をすべて破棄するためです。 したがって、"(?>.*)." はどんな文字列
にもマッチしません。 最初に ".*" が可能な限りすべての文字にマッチする
ため、末尾の "." にマッチする文字が残らず失敗します。 アトミックグルー
プの内部に保存されたスタック上の位置も、その前に戻れる位置もないため、
正規表現全体のマッチが失敗します。

Added in version 3.11.


"(?P<name>...)"
~~~~~~~~~~~~~~~

通常の丸括弧に似ていますが、このグループがマッチした部分文字列はシンボ
リックグループ名 *name* でアクセスできます。グループ名は有効な Python
識別子でなければならず、"bytes" パターンではASCIIの範囲のバイトのみを
含めることができます。各グループ名は 1 個の正規表現内で一度だけ定義さ
れていなければなりません。シンボリックグループは、そのグループが名前付
けされていなかったかのように番号付けされたグループでもあります。

名前付きグループは 3 つのコンテキストで参照できます。パターンが
"(?P<quote>['\"]).*?(?P=quote)" (シングルまたはダブルクオートで囲まれ
た文字列にマッチ) ならば:

+-----------------------------------------+------------------------------------+
| グループ "quote" を参照するコンテキスト | 参照する方法                       |
|=========================================|====================================|
| その同じパターン中                      | * "(?P=quote)" (示したとおり)  *   |
|                                         | "\1"                               |
+-----------------------------------------+------------------------------------+
| マッチオブジェクト *m* の処理時         | * "m.group('quote')"  *            |
|                                         | "m.end('quote')" (など)            |
+-----------------------------------------+------------------------------------+
| "re.sub()" の *repl* 引数へ渡される文字 | * "\g<quote>"  * "\g<1>"  * "\1"   |
| 列中                                    |                                    |
+-----------------------------------------+------------------------------------+

バージョン 3.12 で変更: "bytes" パターンではグループの *名前* にASCII
の範囲("b'\x00'"-"b'\x7f'")のバイトのみを含めることができます。


"(?P=name)"
~~~~~~~~~~~

名前付きグループへの後方参照です。これは *name* という名前の既出のグル
ープがマッチした文字列にマッチします。


"(?#...)"
~~~~~~~~~

コメントです。括弧の中身は単純に無視されます。


"(?=...)"
~~~~~~~~~

"..." が次に続くものにマッチすればマッチしますが、文字列をまったく消費
しません。これは *先読みアサーション (lookahead assertion)* と呼ばれま
す。例えば、"Isaac (?=Asimov)" は "'Isaac '" に、その後に "'Asimov'"
が続く場合にのみ、マッチします。


"(?!...)"
~~~~~~~~~

"..." が次に続くものにマッチしなければマッチします。これは *否定先読み
アサーション (negative lookahead assertion)* です。例えば、"Isaac
(?!Asimov)" は "'Isaac '" に、その後に "'Asimov'" が続か *ない* 場合に
のみ、マッチします。


"(?<=...)"
~~~~~~~~~~

その文字列における現在位置の前に、現在位置で終わる "..." とのマッチが
あれば、マッチします。 これは *後読みアサーション* と呼ばれます。
"(?<=abc)def" は、後読みは 3 文字分戻り、含まれているパターンがマッチ
するか検査するので "'abcdef'" にマッチを見つけます。 含まれるパターン
は、固定長の文字列にのみマッチしなければなりません。 すなわち、 "abc"
や "a|b" は許されますが、"a*" や "a{3,4}" は許されません。 肯定後読み
アサーションで始まるパターンは、検索される文字列の先頭とは決してマッチ
しないことに注意して下さい。 "match()" 関数ではなく "search()" 関数を
使う方が望ましいでしょう:

>>> import re
>>> m = re.search('(?<=abc)def', 'abcdef')
>>> m.group(0)
'def'

この例ではハイフンに続く単語を探します:

>>> m = re.search(r'(?<=-)\w+', 'spam-egg')
>>> m.group(0)
'egg'

バージョン 3.5 で変更: 固定長のグループ参照をサポートするようになりま
した。


"(?<!...)"
~~~~~~~~~~

その文字列における現在位置の前に "..." とのマッチがなければ、マッチし
ます。これは *否定後読みアサーション(negative lookbehind assertion)*
と呼ばれます。肯定後読みアサーションと同様に、含まれるパターンは固定長
の文字列にのみマッチしなければなりません。否定後読みアサーションで始ま
るパターンは検索される文字列の先頭でマッチできます。


"(?(id/name)yes-pattern|no-pattern)"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

指定した *id* または *name* のグループがマッチしていれば "yes-pattern"
に、そうでなければ "no-pattern" にマッチさせようとします。 "no-
pattern" は省略できます。 例えば "(<)?(\w+@\w+(?:\.\w+)+)(?(1)>|$)" は
簡易的なメールアドレスのパターンです。 "'<user@host.com>'" と
"'user@host.com'" にマッチしますが、"'<user@host.com'" や
"'user@host.com>'" の全体にはマッチしません (前者では "re.search()" は
"'user@host.com'" の部分だけを見つけます)。

バージョン 3.12 で変更: グループ *id* にはASCIIの数字のみを含めること
ができます。"bytes" パターンではグループの *名前* にASCIIの範囲
("b'\x00'"-"b'\x7f'")のバイトのみを含めることができます。


特殊シーケンス
--------------

特殊シーケンスは "'\'" と以下のリストの文字から構成されます。 通常文字
が ASCII 数字でも ASCII 英字でもなければ、結果の正規表現は 2 番目の文
字にマッチします。 例えば、"\$" は文字 "'$'" にマッチします。


"\number"
~~~~~~~~~

同じ番号のグループの中身にマッチします。グループは 1 から始まる番号を
つけられます。例えば、 "(.+) \1" は、 "'the the'" あるいは "'55 55'"
にマッチしますが、 "'thethe'" にはマッチしません(グループの後のスペー
スに注意して下さい)。この特殊シーケンスは最初の 99 グループのうちの一
つとのマッチにのみ使えます。 *number* の最初の桁が 0 であるか、
*number* が 3 桁の 8 進数であれば、それはグループのマッチとしてではな
く、 8 進値 *number* を持つ文字として解釈されます。文字クラスの "'['"
と "']'" の間では全ての数値エスケープが文字として扱われます。


"\A"
~~~~

文字列の先頭でのみマッチします。


"\b"
~~~~

空文字列にマッチしますが、単語の先頭か末尾でのみです。単語は単語文字の
並びとして定義されます。形式的には、 "\b" は "\w" と "\W" 文字 (または
その逆) との、あるいは "\w" と文字列の先頭・末尾との境界として定義され
ます。例えば、 "r'\bat\b'" は "'at'" 、 "'at.'"、 "'(at)'" や "'as at
ay'" にはマッチしますが、 "'attempt'" や "'atlas'" にはマッチしません
。

Unicode (str) パターンのデフォルトの単語文字は Unicode の英数字とアン
ダースコアですが、"ASCII" フラグで変更できます。 "LOCALE" フラグを使う
と、単語境界は現在のロケールによって決まります。

注釈:

  文字範囲の中では、Python の文字列リテラルとの互換性のため、"\b" はバ
  ックスペース文字を表します。


"\B"
~~~~

空文字列にマッチしますが、それが単語の先頭か末尾 *でない* ときのみです
。つまり "r'at\B'" は "'athens'"、 "'atom'"、"'attorney'" にマッチしま
すが、 "'at'"、 "'at.'" や "'at!'" にはマッチしません。 "\B" は "\b"
のちょうど反対で、 Unicode パターンにおける単語文字は Unicode 英数字お
よびアンダースコアですが、 これは "ASCII" フラグを使って変更できます。
"LOCALE" フラグが使われているなら単語の境界は現在のロケールによって決
定されます。

バージョン 3.14 で変更: "\B" が空の入力文字列にもマッチするようになり
ました。


"\d"
~~~~

Unicode (str) パターンでは:
   任意の Unicode 10 進数字 (Unicode 文字カテゴリ [Nd])にマッチします
   。これは "[0-9]" とその他多数の数字を含みます。

   "ASCII" フラグを使用すると "[0-9]" にマッチします。

8 ビット (bytes) パターンでは:
   任意のASCII文字の 10 進数字にマッチします。これは "[0-9]" と等価で
   す。


"\D"
~~~~

10 進数字でない任意の文字にマッチします。 "\d" の逆です。

"ASCII" フラグを使用すると "[^0-9]" にマッチします。


"\s"
~~~~

Unicode (str) パターンでは:
   Unicode の空白文字 ("str.isspace()" の定義による) にマッチします。
   "[ \t\n\r\f\v]" に加え、多くの言語の組版規則で必要とされるノーブレ
   ークスペースなど、多数の文字を含みます。

   "ASCII" フラグを使用すると "[ \t\n\r\f\v]" にマッチします。

8 ビット (bytes) パターンでは:
   ASCII 文字セットで空白文字と見なされる文字にマッチします。これは "[
   \t\n\r\f\v]" と等価です。


"\S"
~~~~

空白文字でない任意の文字にマッチします。 "\s" の逆です。

"ASCII" フラグを使用すると "[^ \t\n\r\f\v]" にマッチします。


"\w"
~~~~

Unicode (str) パターンでは:
   Unicode の単語文字にマッチします。 これはすべての Unicode 英数字
   ("str.isalnum()" の定義による) と、アンダースコア ("_") を含みます
   。

   "ASCII" フラグを使用すると "[a-zA-Z0-9_]" にマッチします。

8 ビット (bytes) パターンでは:
   ASCII 文字セットで英数字と見なされる文字にマッチします。これは
   "[a-zA-Z0-9_]" と等価です。"LOCALE" フラグが使われているなら、現在
   のロケールで英数字と見なされる文字およびアンダースコアにマッチしま
   す。


"\W"
~~~~

単語文字でない任意の文字にマッチします。 "\w" の逆です。 デフォルトで
は、アンダースコア ("_") 以外で、"str.isalnum()" が "False" を返す文字
にマッチします。

"ASCII" フラグを使用すると "[^a-zA-Z0-9_]" にマッチします。

"LOCALE" フラグを使うと、現在のロケールで英数字とみなされる文字でもア
ンダースコアでもない文字にマッチします。


"\z"
~~~~

文字列の末尾でのみマッチします。

Added in version 3.14.


"\Z"
~~~~

"\z" と同じです。 古い Python バージョンとの互換性のためにあります。


標準のエスケープ
----------------

Python 文字列リテラルでサポートされている  エスケープシーケンス のほと
んども正規表現パーザで受理されます:

   \a      \b      \f      \n
   \N      \r      \t      \u
   \U      \v      \x      \\

("\b" は単語の境界を表すのに使われ、文字クラス中でのみ "後退
(backspace)" 文字を意味することに注意してください。)

"'\u'"、"'\U'" および "'\N'" エスケープシーケンスは、Unicode (str)パタ
ーン内でのみ認識されます。 バイト列ではエラーとなります。 ASCII 英字の
エスケープで未知のものは将来使うために予約されていて、エラーとして扱わ
れます。

8 進エスケープは限られた形式でのみ含まれます。その最初の桁が 0 である
か、それが 3 桁の 8 進数であるならば、それは 8 進エスケープと見なされ
ます。そうでなければ、それはグループ参照です。文字列リテラルでは、8 進
エスケープは常にたかだか 3 桁長です。

バージョン 3.3 で変更: "'\u'" と "'\U'" エスケープシーケンスが追加され
ました。

バージョン 3.6 で変更: "'\'" と ASCII 英字からなる未知のエスケープはエ
ラーになります。

バージョン 3.8 で変更: "'\N{*name*}'" エスケープシーケンスが追加されま
した。 文字列リテラルと同様に、指定した名前の Unicode 文字に展開されま
す。 ("'\N{EM DASH}'" など)


モジュールの内容
================

このモジュールはいくつかの関数、定数、例外を定義します。このうちいくつ
かの関数は、コンパイル済み正規表現がそなえる完全な機能のメソッドを簡易
にしたものです。些細なものを除くほとんどのアプリケーションは常にコンパ
イル済み形式を使います。


フラグ
------

バージョン 3.6 で変更: フラグ定数は、"enum.IntFlag" のサブクラスである
"RegexFlag" のインスタンスになりました。

class re.RegexFlag

   以下の正規表現オプションを含む "enum.IntFlag" クラスです。

   Added in version 3.11: - added to "__all__"

re.A
re.ASCII

   "\w"、"\W"、"\b"、"\B"、"\d"、"\D"、"\s"、および "\S" において、
   ASCII 文字のみでマッチングを行います。これは Unicode(str) パターン
   でのみ意味があり、バイト列パターンでは無視されます。

   インラインフラグの "(?a)" に相当します。

   注釈:

     "U" フラグは後方互換性のために残されていますが、Python 3 では冗長
     です。 "str" パターンはデフォルトで Unicode マッチングを行い、
     bytes パターンでは Unicode マッチングが許可されないためです。
     "UNICODE" とインラインフラグ "(?u)" も同様に冗長です。

re.DEBUG

   コンパイルした表現に関するデバッグ情報を出力します。

   対応するインラインフラグはありません。

re.I
re.IGNORECASE

   大文字と小文字を区別せずにマッチングを行います。 "[A-Z]" のような式
   は小文字にもマッチします。 "ASCII" フラグで非 ASCII のマッチングを
   無効にしない限り、"Ü" が "ü" にマッチするような Unicode 全体のマッ
   チングも機能します。 "LOCALE" フラグも併用しない限り、現在のロケー
   ルはこのフラグの効果に影響しません。

   インラインフラグの "(?i)" に相当します。

   Unicode パターン "[a-z]" または "[A-Z]" が "IGNORECASE" フラグとあ
   わせて使われたとき、52 の ASCII 文字に加えて 4 の非 ASCII 文字 'İ'
   (U+0130, Latin capital letter I with dot above) 、 'ı' (U+0131,
   Latin small letter dotless i) 、 'ſ' (U+017F, Latin small letter
   long s) および 'K' (U+212A, Kelvin sign) にマッチすることに注意して
   ください。 "ASCII" フラグが使われているなら、文字 'a' から 'z' およ
   び 'A' から 'Z' にのみマッチします。

re.L
re.LOCALE

   "\w"、"\W"、"\b"、"\B" と、大文字と小文字を区別しないマッチングを現
   在のロケールに依存させます。 このフラグは bytes パターンでのみ使え
   ます。

   インラインフラグの "(?L)" に相当します。

   警告:

     このフラグの使用は推奨しません。 代わりに Unicode マッチングを検
     討してください。 ロケールの仕組みは、一度に 1 つの「文化」しか扱
     えず、8 ビットのロケールでしか機能しないため、非常に頼りないもの
     です。 Unicode (str) パターンでは Unicode マッチングがデフォルト
     で有効で、さまざまなロケールや言語を扱えます。

   バージョン 3.6 で変更: "LOCALE" はバイト列パターンにのみ使え、
   "ASCII" と互換ではありません。

   バージョン 3.7 で変更: "LOCALE" フラグがあるコンパイル済み正規表現
   オブジェクトはコンパイル時のロケールに依存しなくなりました。マッチ
   ング時のロケールのみがマッチングの結果に影響します。

re.M
re.MULTILINE

   指定されると、パターン文字 "'^'" は、文字列の先頭および各行の先頭(
   各改行の直後)とマッチします；そしてパターン文字 "'$'" は文字列の末
   尾および各行の末尾 (改行の直前) とマッチします。デフォルトでは、
   "'^'" は、文字列の先頭とだけマッチし、 "'$'" は、文字列の末尾および
   文字列の末尾の改行の直前(がもしあれば)とマッチします。

   インラインフラグの "(?m)" に相当します。

re.NOFLAG

   フラグを何も適用しないことを示し、値は "0" です。 関数のキーワード
   引数のデフォルト値として、または条件に応じて他のフラグと OR で組み
   合わせる初期値として使えます。 デフォルト値として使う例です。

      def myfunc(pattern, text, flag=re.NOFLAG):
          return re.search(pattern, text, flag)

   Added in version 3.11.

re.S
re.DOTALL

   特殊文字 "'.'" を、改行を含む任意の文字と、とにかくマッチさせます；
   このフラグがなければ、 "'.'" は、改行 *以外の* 任意の文字とマッチし
   ます。

   インラインフラグの "(?s)" に相当します。

re.U
re.UNICODE

   Python 3 では、"str" パターンはデフォルトで Unicode 文字にマッチし
   ます。 そのため、このフラグは冗長で **効果はなく**、後方互換性のた
   めだけに残されています。

   マッチングを ASCII 文字に限定するには、"ASCII" を参照してください。

re.X
re.VERBOSE

   このフラグは正規表現を、パターンの論理的な節を視覚的に分割し、コメ
   ントを加えることで、見た目よく読みやすく書けるようにします。パター
   ン中の空白は、文字クラス中にあるときと、エスケープされていないバッ
   クスラッシュの後にあるときと、 "*?" 、 "(?:" や "(?P<...>" のような
   トークン中を除いて無視されます。たとえば、 "(? :" and "* ?" は許さ
   れません。ある行が文字クラス中でもエスケープされていないバックスラ
   ッシュの後でもない "#" を含むなら、一番左のそのような "#" から行末
   までの全ての文字は無視されます。

   つまり、10 進数字にマッチする下記のふたつの正規表現オブジェクトは、
   機能的に等価です:

      a = re.compile(r"""\d +  # 整数部
                         \.    # 小数点
                         \d *  # 小数部の数字""", re.X)
      b = re.compile(r"\d+\.\d*")

   インラインフラグの "(?x)" に相当します。


関数
----

re.compile(pattern, flags=0)

   正規表現パターンを 正規表現オブジェクト にコンパイルします。 このオ
   ブジェクトの "prefixmatch()"、"search()"、その他の後述するメソッド
   でマッチングを行えます。

   *flags* の値を指定して、正規表現の動作を変更できます。 flags の各変
   数を、ビット単位 OR ("|" 演算子) で組み合わせて指定できます。

   シーケンス

      prog = re.compile(pattern)
      result = prog.search(string)

   は、以下と同等です

      result = re.search(pattern, string)

   が、 "re.compile()" を使い、結果の正規表現オブジェクトを保存して再
   利用するほうが、一つのプログラムでその表現を何回も使うときに効率的
   です。

   注釈:

     "re.compile()" やモジュールレベルのマッチング関数に渡した直近のパ
     ターンは、コンパイル済みのものがキャッシュされます。 そのため、一
     度に少数の正規表現しか使わないプログラムでは、正規表現のコンパイ
     ルを気にする必要はありません。

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

   *string* 全体を走査して、正規表現 *pattern* がマッチを発生する最初
   の位置を探して、対応する "Match" を返します。もし文字列内に、そのパ
   ターンとマッチする位置がないならば、 "None" を返します；これは、文
   字列内のある点で長さゼロのマッチを探すこととは異なることに注意して
   下さい。

   *flags* の値を指定して、正規表現の動作を変更できます。 flags の各変
   数を、ビット単位 OR ("|" 演算子) で組み合わせて指定できます。

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

   もし *string* の先頭で 0 個以上の文字が正規表現 *pattern* とマッチ
   すれば、対応する "Match" を返します。もし文字列がパターンとマッチし
   なければ、 "None" を返します；これは長さゼロのマッチとは異なること
   に注意して下さい。

   注釈:

     "MULTILINE" モードでも、各行の先頭ではなく文字列の先頭にだけマッ
     チします。

   *string* 中のどこででもマッチさせたいなら、代わりに "search()" を使
   ってください (search() と prefixmatch() の違い も参照してください)
   。

   *flags* の値を指定して、正規表現の動作を変更できます。 flags の各変
   数を、ビット単位 OR ("|" 演算子) で組み合わせて指定できます。

   この関数には現在 2 つの名前があり、以前から "match()" という名前で
   知られています。 古い Python バージョンとの互換性が必要な場合は、そ
   の名前を使ってください。

   Added in version 3.15.

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

   バージョン 3.15 で ソフト非推奨 <Soft deprecated>: "match()" は
   *soft deprecated* となり、より動作が明確に伝わる別名
   "prefixmatch()" の使用を推奨します。 意図を明確に表すためにこの名前
   を使ってください。 他の言語や正規表現の実装では、Python がこれまで
   "search()" と呼んできた動作を *match* と呼ぶのが一般的です。
   prefixmatch() と match() の違い を参照してください。

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

   *string* 全体が正規表現 *pattern* にマッチするなら、対応する
   "Match" を返します。文字列がパターンにマッチしないなら "None" を返
   します。これは長さ 0 のマッチとは異なることに注意して下さい。

   *flags* の値を指定して、正規表現の動作を変更できます。 flags の各変
   数を、ビット単位 OR ("|" 演算子) で組み合わせて指定できます。

   Added in version 3.4.

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

   *string* を、出現した *pattern* で分割します。 *pattern* 中でキャプ
   チャの丸括弧が使われていれば、パターン中の全てのグループのテキスト
   も結果のリストの一部として返されます。*maxsplit* が 0 でなければ、
   分割は最大 *maxsplit* 回起こり、残りの文字列はリストの最終要素とし
   て返されます。

      >>> re.split(r'\W+', 'Words, words, words.')
      ['Words', 'words', 'words', '']
      >>> re.split(r'(\W+)', 'Words, words, words.')
      ['Words', ', ', 'words', ', ', 'words', '.', '']
      >>> re.split(r'\W+', 'Words, words, words.', maxsplit=1)
      ['Words', 'words, words.']
      >>> re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE)
      ['0', '3', '9']

   セパレータ中にキャプチャグループがあり、それが文字列の先頭にマッチ
   するなら、結果は空文字列で始まります。 同じことが文字列の末尾にも言
   えます。

      >>> re.split(r'(\W+)', '...words, words...')
      ['', '...', 'words', ', ', 'words', '...', '']

   そうして、結果のリストにおいて、セパレータの構成要素は常に同じ相対
   的インデックスに見つかります。

   空のマッチ同士が隣り合うことはありませんが、空でないマッチの直後に
   空のマッチが生じることはあります。

      >>> re.split(r'\b', 'Words, words, words.')
      ['', 'Words', ', ', 'words', ', ', 'words', '.']
      >>> re.split(r'\W*', '...words...')
      ['', '', 'w', 'o', 'r', 'd', 's', '', '']
      >>> re.split(r'(\W*)', '...words...')
      ['', '...', '', '', 'w', '', 'o', '', 'r', '', 'd', '', 's', '...', '', '', '']

   *flags* の値を指定して、正規表現の動作を変更できます。 flags の各変
   数を、ビット単位 OR ("|" 演算子) で組み合わせて指定できます。

   バージョン 3.1 で変更: オプションの flags 引数が追加されました。

   バージョン 3.7 で変更: 空文字列にマッチしうるパターンでの分割をサポ
   ートするようになりました。

   バージョン 3.13 で非推奨: *maxsplit* と *flags* を位置引数として渡
   すことは非推奨です。 将来の Python バージョンでは、これらは キーワ
   ード専用引数 になります。

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

   *string* 内の *pattern* に重複せずにマッチするすべての部分を、文字
   列またはタプルのリストとして返します。 *string* は左から右に走査さ
   れ、マッチは見つかった順に返されます。 結果には空のマッチも含まれま
   す。

   結果はパターン内のキャプチャグループの数によって変わります。 グルー
   プがない場合は、パターン全体にマッチする文字列のリストを返します。
   グループがちょうど 1 つの場合は、そのグループにマッチする文字列のリ
   ストを返します。 複数のグループがある場合は、各グループにマッチする
   文字列のタプルのリストを返します。 キャプチャしないグループは結果の
   形式に影響しません。

   >>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
   ['foot', 'fell', 'fastest']
   >>> re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10')
   [('width', '20'), ('height', '10')]

   *flags* の値を指定して、正規表現の動作を変更できます。 flags の各変
   数を、ビット単位 OR ("|" 演算子) で組み合わせて指定できます。

   バージョン 3.7 で変更: 空でないマッチが前の空マッチの直後から始めら
   れるようになりました。

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

   *string* 中の正規表現 *pattern* の重複しないマッチ全てに渡る
   "Match" オブジェクトを yield する *イテレータ* を返します。
   *string* は左から右へ走査され、マッチは見つかった順で返されます。空
   マッチは結果に含まれます。

   *flags* の値を指定して、正規表現の動作を変更できます。 flags の各変
   数を、ビット単位 OR ("|" 演算子) で組み合わせて指定できます。

   バージョン 3.7 で変更: 空でないマッチが前の空マッチの直後から始めら
   れるようになりました。

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

   *string* 中に出現する最も左の重複しない *pattern* を置換 *repl* で
   置換することで得られる文字列を返します。 パターンが見つからない場合
   、 *string* がそのまま返されます。 *repl* は文字列または関数です。
   *repl* が文字列の場合は、その中の全てのバックスラッシュエスケープが
   処理されます。 "\n" は 1 つの改行文字に変換され、 "\r" はキャリッジ
   リターンに変換される、などです。 ASCII 英字のエスケープで未知のもの
   は将来使うために予約されていて、エラーとして扱われます。 それ以外の
   "\&" のような未知のエスケープは残されます。 "\6" のような後方参照は
   、パターンのグループ 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* が発生するたびにそ
   の関数が呼ばれます。 この関数は一つの "Match" 引数を取り、置換文字
   列を返します。 例えば次のように使います。

      >>> def dashrepl(matchobj):
      ...     if matchobj.group(0) == '-': return ' '
      ...     else: return '-'
      ...
      >>> re.sub('-{1,2}', dashrepl, 'pro----gram-files')
      'pro--gram files'
      >>> re.sub(r'\sAND\s', ' & ', 'Baked Beans And Spam', flags=re.IGNORECASE)
      'Baked Beans & Spam'

   パターンは、文字列でも "Pattern" でも構いません。

   省略可能な引数 *count* は、パターンにマッチした箇所を置換する回数の
   上限です。 *count* は非負の整数でなければなりません。 省略するかゼ
   ロを指定すると、すべての箇所を置換します。

   空のマッチ同士が隣り合うことはありませんが、空でないマッチの直後に
   空のマッチが生じることはあります。 そのため "sub('x*', '-',
   'abxd')" は "'-a-b-d-'" ではなく "'-a-b--d-'" を返します。

   文字列型 *repl* 引数では、上で述べた文字エスケープや後方参照に加え
   て、 "\g<name>" は "(?P<name>...)" 構文で定義された "name" という名
   前のグループがマッチした部分文字列を使い、 "\g<number>" は対応する
   グループ番号を使います。よって "\g<2>" は "\2" と等価ですが、
   "\g<2>0" のような置換においても曖昧になりません。 "\20" は、グルー
   プ 20 への参照として解釈され、グループ 2 への参照にリテラル文字
   "'0'" が続いたものとしては解釈されません。後方参照 "\g<0>" は正規表
   現とマッチした部分文字列全体で置き換わります。

   *flags* の値を指定して、正規表現の動作を変更できます。 flags の各変
   数を、ビット単位 OR ("|" 演算子) で組み合わせて指定できます。

   バージョン 3.1 で変更: オプションの flags 引数が追加されました。

   バージョン 3.5 で変更: マッチしなかったグループは空文字列に置き換え
   られます。

   バージョン 3.6 で変更: *pattern* 中に "'\'" と ASCII 英字からなる未
   知のエスケープがあると、エラーになります。

   バージョン 3.7 で変更: *repl* 内で "'\'" と ASCII 英字からなる未知
   のエスケープがエラーになるようになりました。 空でないマッチの直後に
   空のマッチが生じることがあるようになりました。

   バージョン 3.12 で変更: グループの *id* に使えるのは ASCII 数字だけ
   です。 "bytes" の置換文字列では、グループの *name* に使えるのは
   ASCII 範囲 ("b'\x00'"-"b'\x7f'") のバイトだけです。

   バージョン 3.13 で非推奨: *count* と *flags* を位置引数として渡すこ
   とは非推奨です。 将来の Python バージョンでは、これらは キーワード
   専用引数 になります。

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

   "sub()" と同じ操作を行いますが、タプル "(new_string,
   number_of_subs_made)" を返します。

   *flags* の値を指定して、正規表現の動作を変更できます。 flags の各変
   数を、ビット単位 OR ("|" 演算子) で組み合わせて指定できます。

re.escape(pattern)

   *pattern* 中の特殊文字をエスケープします。 これは正規表現メタ文字を
   含みうる任意のリテラル文字列にマッチしたい時に便利です。

      >>> print(re.escape('https://www.python.org'))
      https://www\.python\.org

      >>> legal_chars = string.ascii_lowercase + string.digits + "!#$%&'*+-.^_`|~:"
      >>> print('[%s]+' % re.escape(legal_chars))
      [abcdefghijklmnopqrstuvwxyz0123456789!\#\$%\&'\*\+\-\.\^_`\|\~:]+

      >>> operators = ['+', '-', '*', '/', '**']
      >>> print('|'.join(map(re.escape, sorted(operators, reverse=True))))
      /|\-|\+|\*\*|\*

   この関数は、バックスラッシュのみをエスケープするべき "sub()" および
   "subn()" における置換文字列に使われてはなりません。例えば:

      >>> digits_re = r'\d+'
      >>> sample = '/usr/sbin/sendmail - 0 errors, 12 warnings'
      >>> print(re.sub(digits_re, digits_re.replace('\\', r'\\'), sample))
      /usr/sbin/sendmail - \d+ errors, \d+ warnings

   バージョン 3.3 で変更: "'_'" 文字がエスケープされなくなりました。

   バージョン 3.7 で変更: 正規表現で特別な意味を持つ文字だけがエスケー
   プされます。結果として、 "'!'"、 "'"'"、 "'%'"、 ""'""、 "','"、
   "'/'"、 "':'"、 "';'"、 "'<'"、 "'='"、 "'>'"、 "'@'"、 と ""`"" は
   もはやエスケープされません。

re.purge()

   正規表現キャッシュをクリアします。


例外
----

exception re.PatternError(msg, pattern=None, pos=None)

   ここで説明する関数に渡した文字列が有効な正規表現でない場合 (例えば
   括弧が対応していない場合) や、コンパイルやマッチングの途中で他のエ
   ラーが起きた場合に送出される例外です。 文字列内にパターンとのマッチ
   がないこと自体は、エラーではありません。 "PatternError" インスタン
   スには次の追加属性があります。

   msg

      フォーマットされていないエラーメッセージです。

   pattern

      正規表現のパターンです。

   pos

      *pattern* のコンパイルに失敗した場所のインデックスです ("None"
      の場合もあります)。

   lineno

      *pos* に対応する行です ("None" の場合もあります)。

   colno

      *pos* に対応する列です ("None" の場合もあります)。

   バージョン 3.5 で変更: 追加の属性が追加されました。

   バージョン 3.13 で変更: "PatternError" の元の名前は "error" でした
   。 後方互換性のため、"error" は別名として残されています。


正規表現オブジェクト
====================

class re.Pattern

   "re.compile()" が返すコンパイル済み正規表現オブジェクトです。

   パターンは、扱う文字列の型 ("str" または "bytes") を指定できる ジェ
   ネリック型 です。

   バージョン 3.9 で変更: "re.Pattern" は、Unicode (str) パターンか
   bytes パターンかを示す "[]" をサポートしています。 ジェネリックエイ
   リアス型 を参照してください。

Pattern.search(string[, pos[, endpos]])

   *string* 全体を走査して、この正規表現がマッチを発生する最初の位置を
   探して、対応する "Match" を返します。もし文字列内に、そのパターンと
   マッチする位置がないならば、 "None" を返します；これは、文字列内の
   ある点で長さゼロのマッチを探すこととは異なることに注意して下さい。

   オプションの第二引数 *pos* は、文字列のどこから探し始めるかを指定す
   るインデックスで、デフォルトでは 0 です。これは文字列のスライスと完
   全には同じではありません。パターン文字 "'^'" は本当の文字列の先頭と
   改行の直後でマッチしますが、検索を開始するインデックスでマッチする
   とは限りません。

   オプションの引数 *endpos* は文字列がどこまで検索されるかを制限しま
   す。文字列の長さが *endpos* 文字だったかのようになるので、*pos* か
   ら "endpos - 1" の文字に対してだけマッチを探します。*endpos* が
   *pos* よりも小さいと、マッチは見つかりません。そうでなければ、*rx*
   をコンパイル済み正規表現オブジェクトとして、"rx.search(string, 0,
   50)" は "rx.search(string[:50], 0)" と等価です。

      >>> pattern = re.compile("d")
      >>> pattern.search("dog")     # インデックス 0 でマッチする。
      <re.Match object; span=(0, 1), match='d'>
      >>> pattern.search("dog", 1)  # 検索範囲に "d" がないためマッチしない。

Pattern.prefixmatch(string[, pos[, endpos]])

   もし *string* の先頭で 0 個以上の文字がこの正規表現とマッチすれば、
   対応する "Match" を返します。もし文字列がパターンとマッチしなければ
   、 "None" を返します；これは長さゼロのマッチとは異なることに注意し
   て下さい。

   "MULTILINE" モードでも、各行の先頭ではなく文字列の先頭にだけマッチ
   することに注意してください。

   オプションの *pos* および *endpos* 引数は "search()" メソッドのもの
   と同じ意味です。

      >>> pattern = re.compile("o")
      >>> pattern.prefixmatch("dog")     # "o" は "dog" の先頭にないためマッチしない。
      >>> pattern.prefixmatch("dog", 1)  # "o" は "dog" の 2 文字目なのでマッチする。
      <re.Match object; span=(1, 2), match='o'>

   *string* 中のどこででもマッチさせたいなら、代わりに "search()" を使
   ってください (search() と prefixmatch() の違い も参照してください)
   。

   このメソッドには現在 2 つの名前があり、以前から "match()" という名
   前で知られています。 古い Python バージョンとの互換性が必要な場合は
   、その名前を使ってください。

   Added in version 3.15.

Pattern.match(string[, pos[, endpos]])

   バージョン 3.15 で ソフト非推奨 <Soft deprecated>: "match()" は
   *soft deprecated* となり、より動作が明確に伝わる別名
   "prefixmatch()" の使用を推奨します。 意図を明確に表すためにこの名前
   を使ってください。 他の言語や正規表現の実装では、Python がこれまで
   "search()" と呼んできた動作を *match* と呼ぶのが一般的です。
   prefixmatch() と match() の違い を参照してください。

Pattern.fullmatch(string[, pos[, endpos]])

   *string* 全体がこの正規表現にマッチするなら、対応する "Match" を返
   します。文字列がパターンにマッチしないなら "None" を返します。これ
   は長さ 0 のマッチとは異なることに注意して下さい。

   オプションの *pos* および *endpos* 引数は "search()" メソッドのもの
   と同じ意味です。

      >>> pattern = re.compile("o[gh]")
      >>> pattern.fullmatch("dog")      # "o" は "dog" の先頭にないためマッチしない。
      >>> pattern.fullmatch("ogre")     # 文字列全体はマッチしない。
      >>> pattern.fullmatch("doggie", 1, 3)   # 指定した範囲内でマッチする。
      <re.Match object; span=(1, 3), match='og'>

   Added in version 3.4.

Pattern.split(string, maxsplit=0)

   "split()" 関数にこのコンパイル済みパターンを使うのと同じです。

Pattern.findall(string[, pos[, endpos]])

   "findall()" 関数にこのコンパイル済みパターンを使うのと似ていますが
   、オプションの *pos* および *endpos* 引数で "search()" のように検索
   範囲を制限できます。

Pattern.finditer(string[, pos[, endpos]])

   "finditer()" 関数にこのコンパイル済みパターンを使うのと似ていますが
   、オプションの *pos* および *endpos* 引数で "search()" のように検索
   範囲を制限できます。

Pattern.sub(repl, string, count=0)

   "sub()" 関数にこのコンパイル済みパターンを使うのと同じです。

Pattern.subn(repl, string, count=0)

   "subn()" 関数にこのコンパイル済みパターンを使うのと同じです。

Pattern.flags

   正規表現のマッチングフラグです。これは "compile()" に与えられたフラ
   グ、パターン中の "(?...)" インラインフラグ、およびパターンが
   Unicode 文字列だった時の "UNICODE" のような暗黙のフラグの組み合わせ
   です。

Pattern.groups

   パターン中のキャプチャグループの数です。

Pattern.groupindex

   "(?P<id>)" で定義されたあらゆるシンボリックグループ名をグループ番号
   へ写像する辞書です。シンボリックグループがパターン中で全く使われて
   いなければ、この辞書は空です。

Pattern.pattern

   パターンオブジェクトがコンパイルされた元のパターン文字列です。

バージョン 3.7 で変更: "copy.copy()" および "copy.deepcopy()" をサポー
トするようになりました。コンパイル済み正規表現オブジェクトはアトミック
であると見なされます。


マッチオブジェクト
==================

マッチオブジェクトのブール値は常に "True" です。 "match()" および
"search()" はマッチがないとき "None" を返すので、マッチがあるか単純な
"if" 文で判定できます。

   if match := re.search(pattern, string):
       process(match)

class re.Match

   "match" や "search" が成功したときに返されるマッチオブジェクトです
   。

   マッチは、マッチした文字列の型 ("str" または "bytes") を指定できる
   ジェネリック型 です。

   バージョン 3.9 で変更: "re.Match" は、Unicode (str) のマッチか
   bytes のマッチかを示す "[]" をサポートしています。 ジェネリックエイ
   リアス型 を参照してください。

Match.expand(template)

   Return the string obtained by doing backslash substitution on the
   template string *template*, as done by the "sub()" method. Escapes
   such as "\n" are converted to the appropriate characters, and
   numeric backreferences ("\1", "\2") and named backreferences
   ("\g<1>", "\g<name>") are replaced by the contents of the
   corresponding group. The backreference "\g<0>" will be replaced by
   the entire match.

   バージョン 3.5 で変更: マッチしなかったグループは空文字列に置き換え
   られます。

Match.group([group1, ...])

   マッチの 1 つ以上のサブグループを返します。 引数が 1 つの場合、結果
   は単一の文字列です。 引数が複数の場合、結果は引数ごとに 1 つの要素
   を持つタプルです。 引数を指定しない場合、*group1* のデフォルトはゼ
   ロで、マッチ全体を返します。 *groupN* 引数がゼロの場合、対応する戻
   り値はマッチした文字列全体です。 正の整数の場合は、対応する丸括弧の
   グループにマッチした文字列です。 グループ番号が負の場合や、パターン
   内に定義されたグループ数を超える場合は "IndexError" 例外を送出しま
   す。 グループがパターン内のマッチしなかった部分に含まれる場合、対応
   する結果は "None" です。 複数回マッチした部分にグループが含まれる場
   合は、最後のマッチを返します。

      >>> m = re.search(r"\A(\w+) (\w+)", "Norwegian Blue, pining for the fjords")
      >>> m.group(0)       # マッチ全体
      'Norwegian Blue'
      >>> m.group(1)       # 最初の丸括弧のサブグループ。
      'Norwegian'
      >>> m.group(2)       # 2 番目の丸括弧のサブグループ。
      'Blue'
      >>> m.group(1, 2)    # 引数が複数ならタプルを返す。
      ('Norwegian', 'Blue')

   正規表現が "(?P<name>...)" 構文を使うなら、 *groupN* 引数はグループ
   名でグループを識別する文字列でも構いません。文字列引数がパターン中
   でグループ名として使われていなければ、 "IndexError" 例外が送出され
   ます。

   やや複雑な例:

      >>> m = re.search(r"(?P<adjective>\w+) (?P<animal>\w+)", "killer rabbit")
      >>> m.group('adjective')
      'killer'
      >>> m.group('animal')
      'rabbit'

   名前付きグループはインデックスでも参照できます:

      >>> m.group(1)
      'killer'
      >>> m.group(2)
      'rabbit'

   あるグループが複数回マッチすると、その最後のマッチにのみアクセスで
   きます:

      >>> m = re.search(r"(..)+", "a1b2c3")  # 3 回マッチする。
      >>> m.group(1)                         # 最後のマッチだけを返す。
      'c3'

Match.__getitem__(g)

   これは "m.group(g)" と同等です。これでマッチの個別のグループに簡単
   にアクセスできます:

      >>> m = re.search(r"(\w+) (\w+)", "Norwegian Blue, pining for the fjords")
      >>> m[0]       # マッチ全体
      'Norwegian Blue'
      >>> m[1]       # 最初の丸括弧のサブグループ。
      'Norwegian'
      >>> m[2]       # 2 番目の丸括弧のサブグループ。
      'Blue'

   名前付きグループもサポートされています。

      >>> m = re.search(r"(?P<adjective>\w+) (?P<animal>\w+)", "killer rabbit")
      >>> m['adjective']
      'killer'
      >>> m['animal']
      'rabbit'

   Added in version 3.6.

Match.groups(default=None)

   このマッチの、1 からパターン中のグループ数まで、全てのサブグループ
   を含むタプルを返します。*default* 引数はマッチに関係しなかったグル
   ープに使われます。デフォルトでは "None" です。

   例えば:

      >>> m = re.search(r"(\d+)\.(\d+)", "24.1632")
      >>> m.groups()
      ('24', '1632')

   小数点およびその後の全てをオプションにすると、全てのグループがマッ
   チに関係するとは限りません。 そういったグループは *default* 引数が
   与えられない限りデフォルトで "None" になります。

      >>> m = re.search(r"(\d+)\.?(\d+)?", "24")
      >>> m.groups()      # 2 番目のグループのデフォルトは None。
      ('24', None)
      >>> m.groups('0')   # 2 番目のグループのデフォルトを '0' にする。
      ('24', '0')

Match.groupdict(default=None)

   このマッチの、全ての *名前付き* サブグループを含む、サブグループ名
   をキーとする辞書を返します。 *default* 引数はマッチに関係しなかった
   グループに使われます。デフォルトは "None" です。例えば:

      >>> m = re.search(r"(?P<adjective>\w+) (?P<animal>\w+)", "killer rabbit")
      >>> m.groupdict()
      {'adjective': 'killer', 'animal': 'rabbit'}

Match.start([group])
Match.end([group])

   *group* がマッチした部分文字列の先頭と末尾のインデックスを返します
   。 *group* はデフォルトで 0 (マッチした部分文字列全体という意味) で
   す。 *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'

Match.span([group])

   マッチ *m* について、2 タプル "(m.start(group), m.end(group))" を返
   します。 *group* がマッチに寄与していなければ、これは "(-1, -1)" で
   す。 *group* はデフォルトで 0 、マッチ全体です。

Match.pos

   正規表現オブジェクト の "search()" や "match()" に渡された *pos* の
   値です。これは正規表現エンジンがマッチを探し始める位置の文字列のイ
   ンデックスです。

Match.endpos

   正規表現オブジェクト の "search()" や "match()" に渡された *endpos*
   の値です。これは正規表現エンジンがそれ以上は進まない文字列のインデ
   ックスです。

Match.lastindex

   最後にマッチしたキャプチャグループの整数インデックスです。どのグル
   ープも全くマッチしなければ "None" です。例えば、表現 "(a)b" 、
   "((a)(b))" や "((ab))" が "'ab'" に適用されると "lastindex == 1" と
   なり、同じ文字列に "(a)(b)" が適用されると "lastindex == 2" となり
   ます。

Match.lastgroup

   最後にマッチしたキャプチャグループの名前です。そのグループに名前が
   ないか、どのグループも全くマッチしていなければ "None" です。

Match.re

   このマッチインスタンスを生じさせた "match()" または "search()" メソ
   ッドの属する 正規表現オブジェクト です。

Match.string

   "match()" や "search()" へ渡された文字列です。

バージョン 3.7 で変更: "copy.copy()" および "copy.deepcopy()" をサポー
トするようになりました。マッチオブジェクトはアトミックであると見なされ
ます。


正規表現の使用例
================


ペアの検出
----------

この例では、マッチオブジェクトをより美しく表示するために、この補助関数
を使用します:

   def displaymatch(match):
       if match is None:
           return None
       return '<Match: %r, groups=%r>' % (match.group(), match.groups())

あなたがポーカープログラムを書いているとします。プレイヤーの手札は 5
文字の文字列によって表され、それぞれの文字が 1 枚のカードを表します。
"a" はエース、 "k" はキング、 "q" はクイーン、 "j" はジャック、 "t" は
10、そして "2" から "9" はその数字のカードを表します。

与えられた文字列が有効な手札であるか見るには、以下のようにできます:

   >>> valid_hand_re = re.compile(r"^[a2-9tjqk]{5}$")
   >>> displaymatch(valid_hand_re.search("akt5q"))  # 有効。
   "<Match: 'akt5q', groups=()>"
   >>> displaymatch(valid_hand_re.search("akt5e"))  # 無効。
   >>> displaymatch(valid_hand_re.search("akt"))    # 無効。
   >>> displaymatch(valid_hand_re.search("727ak"))  # 有効。
   "<Match: '727ak', groups=()>"

最後の手札、 ""727ak"" 、はペア、すなわち同じ値の 2 枚のカードを含みま
す。正規表現でこれにマッチするには、このように後方参照を使えます:

   >>> pair_re = re.compile(r".*(.).*\1")
   >>> displaymatch(pair_re.prefixmatch("717ak"))     # 7 のペア。
   "<Match: '717', groups=('7',)>"
   >>> displaymatch(pair_re.prefixmatch("718ak"))     # ペアなし。
   >>> displaymatch(pair_re.prefixmatch("354aa"))     # エースのペア。
   "<Match: '354aa', groups=('a',)>"

ペアになっているのがどのカードか調べるには、このようにマッチオブジェク
トの "group()" メソッドを使えます:

   >>> pair_re = re.compile(r".*(.).*\1")
   >>> pair_re.prefixmatch("717ak").group(1)
   '7'

   # prefixmatch() は group() メソッドのない None を返すため、エラーになる。
   >>> pair_re.prefixmatch("718ak").group(1)
   Traceback (most recent call last):
     File "<pyshell#23>", line 1, in <module>
       pair_re.prefixmatch("718ak").group(1)
   AttributeError: 'NoneType' object has no attribute 'group'

   >>> pair_re.prefixmatch("354aa").group(1)
   'a'


scanf() をシミュレートする
--------------------------

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-7]+"                                 |
+----------------------------------+-----------------------------------------------+
| "%s"                             | "\S+"                                         |
+----------------------------------+-----------------------------------------------+
| "%u"                             | "\d+"                                         |
+----------------------------------+-----------------------------------------------+
| "%x", "%X"                       | "[-+]?(0[xX])?[\dA-Fa-f]+"                    |
+----------------------------------+-----------------------------------------------+

次のような文字列からファイル名と数値を取り出すとします。

   /usr/sbin/sendmail - 0 errors, 4 warnings

"scanf()" なら、次のような書式を使います。

   %s - %d errors, %d warnings

対応する正規表現は次のとおりです。

   (\S+) - (\d+) errors, (\d+) warnings


search() と prefixmatch() の違い
--------------------------------

Python は、正規表現に基づく異なる基本操作を提供しています。

* "re.prefixmatch()" は文字列の先頭だけでマッチを調べます。

* "re.search()" は文字列内の任意の位置でマッチを調べます (Perl のデフ
  ォルトの動作です)。

* "re.fullmatch()" は文字列全体がマッチするかを調べます。

例えば:

   >>> re.prefixmatch("c", "abcdef")  # マッチしない。
   >>> re.search("c", "abcdef")       # マッチする。
   <re.Match object; span=(2, 3), match='c'>
   >>> re.fullmatch("p.*n", "python") # マッチする。
   <re.Match object; span=(0, 6), match='python'>
   >>> re.fullmatch("r.*n", "python") # マッチしない。

"'^'" で始まる正規表現を "search()" で使って、マッチを文字列の先頭での
みに制限できます:

   >>> re.prefixmatch("c", "abcdef")  # マッチしない。
   >>> re.search("^c", "abcdef")      # マッチしない。
   >>> re.search("^a", "abcdef")      # マッチする。
   <re.Match object; span=(0, 1), match='a'>

ただし "MULTILINE" モードでは、"prefixmatch()" は文字列の先頭だけにマ
ッチするのに対し、"'^'" で始まる正規表現を "search()" で使うと、各行の
先頭にマッチします。

   >>> re.prefixmatch("X", "A\nB\nX", re.MULTILINE)  # マッチしない。
   >>> re.search("^X", "A\nB\nX", re.MULTILINE)  # マッチする。
   <re.Match object; span=(4, 5), match='X'>


prefixmatch() と match() の違い
-------------------------------

"match()" 関数とメソッドよりも、長い名前の "prefixmatch()" を推奨する
のはなぜでしょうか。

Python に正規表現が追加されて以降、他の多くの言語にも正規表現ライブラ
リが加わりました。 その中でも広く使われている言語では、Python の
"search()" に当たる、位置を固定しない動作を API で *match* と呼んでい
ます。 そのため、他の言語に慣れていて、Python の API が一般的な慣習と
異なることを知らない人がコードを読み書きするとき、単に *match* と書か
れていると動作が分かりにくくなることがあります。

Zen Of Python ("python3 -m this") の言葉に、*「暗黙的であるより明示的
であるほうがよい」* というものがあります。 "prefixmatch()" という名前
を見れば、意図した動作を理解しやすいでしょう。 "match()" では、Python
に以前からあるこの注意点を知らない人にとって、意図した動作に疑問が残り
ます。

古い "match()" という名前は 30 年以上コードで使われているため、削除す
る予定は **ありません**。 これは *soft deprecated* になっています。 古
い Python バージョンをサポートするコードでは引き続き "match()" を使い
、新しいコードでは "prefixmatch()" を優先してください。

Added in version 3.15: "prefixmatch()"

バージョン 3.15 で ソフト非推奨 <Soft deprecated>: "match()"


電話帳の作成
------------

"split()" は渡されたパターンで文字列を分割してリストにします。このメソ
ッドは、テキストデータをデータ構造に変換して、読みやすくしたり、以下の
例で実演する電話帳作成のように Python で編集したりしやすくするのに、非
常に役に立ちます。

最初に、入力を示します。通常、これはファイルからの入力になるでしょう。
ここでは、3重引用符の書式とします。

   >>> text = """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+", text)
   >>> 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, maxsplit=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, maxsplit=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.'


すべての副詞を見つける
----------------------

"search()" は最初のパターンにのみマッチしますが、 "findall()" は出現す
る *全ての* パターンにマッチします。例えば、ライターがあるテキストの全
ての副詞を見つけたいなら、以下のように "findall()" を使えます:

   >>> text = "He was carefully disguised but captured quickly by police."
   >>> re.findall(r"\w+ly\b", text)
   ['carefully', 'quickly']


すべての副詞とその位置を見つける
--------------------------------

パターンの全てのマッチについて、マッチしたテキスト以上の情報が必要なら
、文字列ではなく "Match" を返す "finditer()" が便利です。先の例に続い
て、ライターがあるテキストの全ての副詞 *およびその位置* を見つけたいな
ら、以下のように "finditer()" を使えます:

   >>> text = "He was carefully disguised but captured quickly by police."
   >>> for m in re.finditer(r"\w+ly\b", text):
   ...     print('%02d-%02d: %s' % (m.start(), m.end(), m.group(0)))
   07-16: carefully
   40-47: quickly


raw 文字列記法
--------------

Raw 文字列記法 ("r"text"") で正規表現をまともに保てます。それがなけれ
ば、正規表現中のバックスラッシュ ("'\'") を個々にバックスラッシュを前
置してエスケープしなければなりません。例えば、以下の 2 行のコードは機
能的に等価です:

   >>> re.search(r"\W(.)\1\W", " ff ")
   <re.Match object; span=(0, 4), match=' ff '>
   >>> re.search("\\W(.)\\1\\W", " ff ")
   <re.Match object; span=(0, 4), match=' ff '>

リテラルのバックスラッシュにマッチさせたいなら、正規表現中ではエスケー
プする必要があります。Raw 文字列記法では、"r"\\""  になります。Raw 文
字列記法を用いないと、""\\\\"" としなくてはならず、以下のコードは機能
的に等価です:

   >>> re.search(r"\\", r"\\")
   <re.Match object; span=(0, 1), match='\\'>
   >>> re.search("\\\\", r"\\")
   <re.Match object; span=(0, 1), match='\\'>


トークナイザの作成
------------------

トークナイザやスキャナ は文字列を解析し、文字のグループにカテゴリ分け
します。これはコンパイラやインタプリタを書くうえで役立つ第一段階です。

テキストのカテゴリは正規表現で指定されます。この技法では、それらを一つ
のマスター正規表現に結合し、マッチの連続についてループします:

   from typing import NamedTuple
   import re

   class Token(NamedTuple):
       type: str
       value: int | float | str
       line: int
       column: int

   def tokenize(code):
       keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'}
       token_specification = [
           ('NUMBER',   r'\d+(\.\d*)?'),  # 整数または小数
           ('ASSIGN',   r':='),           # 代入演算子
           ('END',      r';'),            # 文の終端
           ('ID',       r'[A-Za-z]+'),    # 識別子
           ('OP',       r'[+\-*/]'),      # 算術演算子
           ('NEWLINE',  r'\n'),           # 改行
           ('SKIP',     r'[ \t]+'),       # スペースとタブを読み飛ばす
           ('MISMATCH', r'.'),            # それ以外の文字
       ]
       tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification)
       line_num = 1
       line_start = 0
       for mo in re.finditer(tok_regex, code):
           kind = mo.lastgroup
           value = mo.group()
           column = mo.start() - line_start
           if kind == 'NUMBER':
               value = float(value) if '.' in value else int(value)
           elif kind == 'ID' and value in keywords:
               kind = value
           elif kind == 'NEWLINE':
               line_start = mo.end()
               line_num += 1
               continue
           elif kind == 'SKIP':
               continue
           elif kind == 'MISMATCH':
               raise RuntimeError(f'{value!r} unexpected on line {line_num}')
           yield Token(kind, value, line_num, column)

   statements = '''
       IF quantity THEN
           total := total + price * quantity;
           tax := price * 0.05;
       ENDIF;
   '''

   for token in tokenize(statements):
       print(token)

このトークナイザは以下の出力を作成します:

   Token(type='IF', value='IF', line=2, column=4)
   Token(type='ID', value='quantity', line=2, column=7)
   Token(type='THEN', value='THEN', line=2, column=16)
   Token(type='ID', value='total', line=3, column=8)
   Token(type='ASSIGN', value=':=', line=3, column=14)
   Token(type='ID', value='total', line=3, column=17)
   Token(type='OP', value='+', line=3, column=23)
   Token(type='ID', value='price', line=3, column=25)
   Token(type='OP', value='*', line=3, column=31)
   Token(type='ID', value='quantity', line=3, column=33)
   Token(type='END', value=';', line=3, column=41)
   Token(type='ID', value='tax', line=4, column=8)
   Token(type='ASSIGN', value=':=', line=4, column=12)
   Token(type='ID', value='price', line=4, column=15)
   Token(type='OP', value='*', line=4, column=21)
   Token(type='NUMBER', value=0.05, line=4, column=23)
   Token(type='END', value=';', line=4, column=27)
   Token(type='ENDIF', value='ENDIF', line=5, column=4)
   Token(type='END', value=';', line=5, column=9)

[Frie09] Friedl, Jeffrey. Mastering Regular Expressions. 3rd ed.,
         O'Reilly Media, 2009. 当書の第三版ではもはや Python について
         まったく取り扱っていませんが、初版では良い正規表現を書くこと
         を綿密に取り扱っていました。
