K3. メタ文字の使用 |
バックスラッシュ (\) バックスラッシュ文字には複数の使用方法があります。英数字ではない文字が後に続く場合、その文字の持つ特殊な意味が無くなります。エスケープ文字としてのこのバックスラッシュの使い方は、文字クラスの内部と外部のいずれにおいても適用されます。 例えば、* 文字にマッチさせたい場合はパターン内に \* と記述します。このエスケープ文字が無い場合に後続する文字がメタ文字として解釈されるかどうかに関係なく、エスケープ操作は適用されます。その為、英数字ではない文字がそれ自身を指定するには常にバックスラッシュを前に置くのが安全です。特にバックスラッシュそのものにマッチさせたい場合は \\と記述します。 パターンにPCRE_EXTENDEDオプションが含まれている場合、パターン内の空白文字(文字クラス内を除く)、文字クラス外の # と次の改行文字の間にある文字は無視されます。空白文字や # 文字をパターン内に含める為に、エスケープ文字としてのバックスラッシュを使うことが出来ます。 \Q と\Eで囲むことによって文字のシーケンスからその特殊な意味を無くすことが出来ます。\Q...\E シーケンスは文字クラスの内部と外部どちらでも適用されます。 印刷不可能な文字 バックスラッシュを使って、印刷不可能な文字を目に見える形式でパターン内に埋め込むことが出来ます。パターンの最後に置く2進数の0を除いて、印刷不可能文字の場所に制限はありませが、パターンがテキストエディターで作成される場合は、通常、以下のエスケープシーケンスを使用するほうが2進数字を使用するよりも簡単です。
\cx の具体的な効果は次の通りです。xが小文字の場合、大文字に変換されます。次に、文字のビット6(16進数40)が反転されます。その為 \cz は16進数1Aになりますが、\c{ は16進数3Bになり、\c; は16進数7Bになります。 \x の後では0から2までの16進数字が読み込まれます(大文字でも小文字でも構いません)。 \0 の後では、さらに2つの8進数字が読み込まれます。いずれの場合も、数字が2桁よりも少ない場合には現在あるもののみが使われます。したがって、\0\x\07 のシーケンスは2つの2進の0と、それに続く BEL 文字(コード値7)を指定します。最初の0に続くパターン文字が8進数字の場合は、0の後に2桁の数字を置くようにしてください。 0でない数字の後に続くバックスラッシュの使い方は複雑です。文字クラスの外では、PCREはバックスラッシュおよび後続の数字を10進数として読み込みます。数字が10より小さい場合、または表現内に少なくともそれと同じ数のキャプチャ用左括弧がある場合は、シーケンス全体が後方参照として扱われます。 文字クラスの中、または10進数が9より大きく、キャプチャ用サブパターンがその数よりも少ない場合は、PCREはバックスラッシュに続く8進数字を3つまで再読み込みし、値の最下位の8ビットから1バイトを作成します。それ以降の数字は全てそれ自身を意味します。以下に例を記します。
3桁以上の8進数字は読み取られないため、100以上の8進の値は先行0をつけないように注意してください。 1バイト値を定義するシーケンスは全て、文字クラスの内部と外部のいずれでも使用することが出来ます。文字クラス内ではシーケンス\bはbackspace文字(16進数08)として解釈され、シーケンス\X は文字の"X"として解釈されます。文字クラス外ではこれらのシーケンスは別の意味になります。 包括的な文字型 バックスラッシュの3つ目の使用法として、包括的な文字型を指定することが出来ます。以下の記述は常に認識されます。 ◆\d 10進数字 ◆\D 10進数字ではない文字 ◆\s 空白文字 ◆\S 空白文字ではない文字 ◆\w 「単語」文字 ◆\W 「非単語」文字 エスケープシーケンスの各ペアによって、文字の完全なセットは2つの別々なセットに分割されます。任意の文字は各ペアのいずれか一方のみにマッチします。 これらの文字型シーケンスは、文字クラスの内部と外部のいずれでも使用することが出来ます。それぞれが、該当する型の1つの文字にマッチします。現在のマッチポイントが対象文字列の末尾にある場合はマッチする文字が無いため、全て失敗します。 \s はVT文字(コード11)にはマッチしません。これはPOSIXの"space"クラスとは異なります。\s文字はHT (9)、LF (10)、FF (12)、CR (13)、space (32)です。 簡単な言明 バックスラッシュの4つ目の使用法は簡単な言明です。言明によって、対象文字列内の文字を消費することなく、マッチがある特定のポイントでのみ可能だという条件を指定します。より複雑な言明のためのサブパターンの使用方法は後ほど記載します。バックスラッシュの言明は以下の通りです。 ◆\b 単語境界 ◆\B 非単語境界 ◆\A 対象の始まり ◆\Z 対象の終わり、或いは終端の改行の前 ◆\z 対象の終わり ◆\G 対象内の最初のマッチ位置 これらの言明は文字クラス内では使えない場合があります(ただし、\bは文字クラス内では別の意味を持ち、バックスペース文字になるので注意してください)。 ハット記号 (^) とドル記号($) デフォルトのマッチコードでは、文字クラスの外にあるハット記号は、現在のマッチポイントが対象文字列の始まりにある場合にのみ真になる言明です。文字クラスの中では、ハット記号は全く別の意味を持ちます(下記参照)。 多数の選択肢が含まれている場合、ハット記号はパターンの最初の文字である必要はありません。ただし、パターンがその選択肢にマッチする場合は、ハット記号はそれを含むそれぞれの選択肢の最初にある必要があります。可能な選択肢が全てハット記号で始まっている場合、つまりパターンが対象の始まりにのみマッチするよう制限されている場合、そのパターンは「固定」パターンと呼ばれます。(パターンが固定になる構成は他にもあります)。 ドル記号は現在のマッチポイントが対象の文字列の終わりにあるか、または文字列の終端にある改行文字の直前にある場合にのみ真になる言明です(デフォルト)。多数の選択肢が含まれている場合、ドル記号はパターンの終わりの文字である必要はありませんが、それが含まれている選択肢の最後の文字である必要があります。ドル記号には文字クラス内での特別な意味はありません。 PCRE_MULTILINEオプションが設定されている場合、ハット記号とドル記号は別の意味を持ちます。この場合、対象文字列の始まりと終わりにマッチするだけでなく、対象文字列内にある改行文字の直前直後にもそれぞれマッチします。例えば、複数行モードではパターン/^abc$/は対象文字列"def\nabc"(\nは改行文字)にマッチしますが、複数行モードで無い場合はマッチしません。したがって、全ての選択肢が^で始まっている為に単一行モードでは固定になっているパターンも、複数行では固定にならず、pcre_exec()のstartoffset引数が0でない場合はハット記号にマッチすることができます。 フルストップ(ピリオド、ドット) 文字クラスの外では、パターン内のピリオドは、印刷不可能文字を含む対象内のいずれの文字にもマッチしますが、改行にはマッチしません(デフォルトでは)。ピリオドの処理は、ハット記号とドル記号の処理とは完全に異なります。唯一の共通点はどちらも改行文字と関連するということだけです。ピリオドには文字クラス内での特別な意味はありません。 角括弧と文字クラス 開き角括弧は文字クラスの始まり表し、閉じ角括弧は終わりを表します。閉じ角括弧だけでは特別な意味は持ちません。閉じ角括弧を文字クラスの構成要素としたい場合は、クラス内の最初のデータ文字にする(ハット記号がある場合は最初のハット記号の後)か、バックスラッシュでエスケープする必要があります。 文字クラスは対象の文字列内の1つの文字とマッチします。文字クラス定義の最初の文字がハット記号ではない場合、マッチした文字は文字クラスによって定義された文字のセット内になくてはいけません。クラス定義の最初の文字がハット記号の場合、対象の文字は文字クラスによって定義されたセット内にあってはいけません。文字クラスの構成要素としてハット記号が必要な場合、最初の文字に使用しないか、バックスラッシュでエスケープしてください。 例えば、クラス文字[aeiou]は全ての小文字母音字にマッチしますが、[^aeiou]は小文字母音字でない全ての文字にマッチします。ハット記号は文字クラス内に無い文字を使って、文字クラス内にある文字を指定することの出来る便利な表記方法です。ハット記号で始まる文字クラスは言明ではありません。対象の文字列から文字を消費しているので、現在のポインタが文字列の終わりにある場合は失敗します。 大文字と小文字の区別をしないマッチ設定をした場合、文字クラス内の文字は大文字と小文字の両方を表します。 マイナス(ハイフン)記号を使って、文字クラス内の文字の範囲を指定することが出来ます。例えば[d-m]はdとmの間のあらゆる文字(dとmを含む)にマッチします。マイナス記号をそれ自身として文字クラスで使いたい場合は、バックスラッシュでエスケープするか、文字クラスの最初か最後など、範囲を示すと解釈されない場所に置いてください。 リテラル文字"]"を、文字範囲を示す最後の文字として使うことは出来ません。[W-]46]のようなパターンは、リテラル文字列"46]"が後ろに続く"W"と"-"の2文字からなるクラスとして解釈され、"W46]"や"-46]"にマッチします。ただし、"]" がバックスラッシュでエスケープされている場合は文字範囲の終わりとして解釈され、[W-\]46]は範囲指定の後に2文字が続く文字クラスとして解釈されます。"]"の8進法、または16進法の表現も文字範囲の終わりを指定することが出来ます。 文字型 \d、\D、\p、\P、\s、\S、\w、\W も文字クラス内で使うことができ、マッチする文字をクラスに追加することが出来ます。 文字クラス内で認識されるメタ文字はバックスラッシュ、ハイフン(文字範囲指定として解釈される場所にある場合のみ)、ハット記号(文字クラスの最初にある場合のみ)開き角括弧(POSIX 文字クラス名の始まりとして解釈される場合のみ。次項参照)、終端の閉じ角括弧のみですが、その他の非英数文字をエスケープしても問題ありません。 POSIX文字クラス PCREでは、文字クラスのPOSIX表記がサポートされています。例えば [01[:alpha:]%] は "0"、"1"、あらゆるアルファベット文字、または"%"にマッチします。サポートされているクラス名は以下のとおりです。 ◆alnum 英字と数字 ◆alpha 英字 ◆ascii 文字コード0~127 ◆blank 空白またはタブのみ ◆cntrl コントロール文字 ◆digit 10進数字(\dと同じ) ◆graph 空白を除く、印刷可能文字 ◆lower 英小文字 ◆print 空白を含む、印刷可能文字 ◆punct 英数字を除く、印刷可能文字 ◆space ホワイトスペース(\sと全く同じではありません) ◆upper 英大文字 ◆word 「単語」文字(\wと同じ) ◆xdigit 16進数字 縦棒(|) 縦棒は選択肢パターンを分けるのに使用します。例えば、パターン gilbert|sullivan は、"gilbert"か"sullivan"のいずれにマッチします。選択肢はいくつでも置くことが出来、空の選択肢も可能です(空の文字列にマッチします)。マッチ処理によって各選択肢が左から右へ試され、最初に成功したものが使用されます。選択肢がサブパターン内にある場合(下記参照)、「成功」はサブパターン内の選択肢とメインパターンの残りの選択肢にマッチすることを意味します。 内部オプション設定 PCRE_CASELESS、PCRE_MULTILINE、PCRE_EXTENDED オプションの設定は、"(?" と")"で囲まれたPerlオプション文字のシーケンスによってパターン内から変更することが出来ます。オプション文字は以下の通りです。 ◆i for PCRE_CASELESS ◆m for PCRE_MULTILINE ◆x for PCRE_EXTENDED 例えば、(?im)は大文字小文字を区別しない複数行のマッチ設定です。ハイフンを前に置くことでこの設定を解除することも可能です。(?im-x)のように設定と解除を組み合わせることもでき、これはPCRE_EXTENDEDを解除すると同時にPCRE_CASELESSとPCRE_MULTILINEを設定します。ハイフンが文字の前と後ろに置かれた場合、オプションは解除されます。 サブパターン サブパターンはネスト可能な丸括弧で囲むことが出来ます。パターンをサブパターンにすると以下の2つが可能になります。 1.選択肢のセットを細分化します。例えば、パターン cat(aract|erpillar|) は"cat"、"cataract"、"caterpillar"のいずれかにマッチします。括弧が無い場合は"cataract"、"erpillar"、または空の文字列にマッチします。 2.サブパターンをキャプチャ用サブパターンとして設定します。開き括弧の数が左から右に数えられ(1から開始)キャプチャ用サブパターンの番号が指定されます。 例えば、文字列"the red king"を次のパターンにマッチさせる場合 the ((red|white) (king|queen)) キャプチャされる部分文字列は"red king"、"red"、"king"で、それぞれ1、2、3と番号が付きます。 括弧に2つの機能があるということが常に役に立つわけではありません。値をキャプチャする必要はないが、サブパターンをグループ分けしたい場合もあります。開き括弧の後に"?:"を置くと、サブパターンはキャプチャを行わず、続くキャプチャ用サブパターンの番号を処理する際にカウントされません。例えば、文字列"the white queen"をパターン the ((?:red|white) (king|queen)) にマッチさせる場合、キャプチャされる部分文字列は"white queen"と"queen"で、1、2と番号が付きます。キャプチャ用サブパターンの数の上限は65535です。キャプチャ用とそうでない全てのサブパターンをネスト出来る深さの上限は200です。 簡略化された表記方法として、キャプチャ用ではないサブパターンの始まりにオプション設定が必要な場合、オプションの文字を"?"と":"の間に置くことが出来ます。したがって、以下の2つのパターン (?i:saturday|sunday) (?:(?i)saturday|sunday) は、全く同じ文字列のセットにマッチします。選択肢は左から右に試され、オプションはサブパターンの終わりに達するまでリセットされないため、1つの選択肢内でのオプション設定は後続する選択肢にも影響を与えます。そのため、上記のパターンは"SUNDAY"と"Saturday"にマッチします。 繰り返し 繰り返しは量指定子によって指定され、次のいずれのアイテムの後ろにも置くことが出来ます。 ◆リテラルデータ文字 ◆. メタ文字 ◆\C エスケープシーケンス ◆単一の文字にマッチする\dなどのエスケープ ◆文字クラス ◆後方参照(次項参照) ◆括弧で囲んだサブパターン(言明ではない場合) 汎用の量指定子は、コンマで区切った2つの数を波括弧で囲むことによって、マッチ出来る数の下限と上限を指定します。数字は65536未満で、最初の数字は2番目の数字以下でなければなりません。 例えば z{2,4} は"zz"、"zzz"、"zzzz"にマッチします。閉じ括弧だけでは特別な意味を持ちません。コンマを残した状態で2番目の数字だけ省略された場合は上限が無く、2番目の数字とコンマが両方とも省略された場合、量指定子は必要なマッチの数を厳密に指定します。 したがって [aeiou]{3,} は少なくとも3連続する母音字にマッチし、もっと多く連続するものにもマッチする場合があります。 一方、 \d{8} は丁度8桁の数字にマッチします。量指定子を使用できない場所、または量指定子のシンタックスにマッチしない場合にある開き波括弧はリテラル文字として扱われます。例えば、{,6}は量指定子ではなく、4つの文字からなるリテラル文字列です。 量指定子{0}の使用も可能で、前の項目や量指定子が存在していないという指定になります。 利便性(及び従来との互換性)の為に、最もよく使われる3つの量指定子は1文字で表すことができます。 ◆* — {0,}と同じ ◆+ — {1,}と同じ ◆? — {0,1}と同じ 次のように、一致する文字がないサブパターンと上限のない量指定子の組み合わせで、無限ループを作成することが出来ます。 (a?)* デフォルトでは量指定子は「貪欲」で、残りのパターンを失敗させることなく出来るだけ多く(回数の上限まで)マッチします。これが問題となる典型的な例として、Cプログラムのコメントにマッチさせようとした場合があげられます。コメントは/* と */の間に記述されますが、コメント内にも個別の*や/が現れる場合があります。Cのコメントにマッチさせようと、 /\*.*\*/ のパターンを /* first comment */ not comment /* second comment */ の文字列に適用しても、*が貪欲である為に文字列全体にマッチしてしまうので失敗します。 しかし、量指定子に疑問符がついている場合は貪欲ではなくなります。代わりに出来るだけ少ない回数でマッチするようになり、 /\*.*?\*/ のパターンはCコメントに正しくマッチします。量指定子の意味は変わらず、マッチする回数だけが変化します。疑問符のこの使い方と本来の量指定子としての使い方を混同しないように注意してください。疑問符には2通りの使い方があるので、次のように重複して使うことも出来ます。 \d??\d これは指定によって1桁にマッチしますが、残りのパターンがマッチする唯一の方法である場合は2桁にマッチすることも出来ます。 PCRE_UNGREEDYオプションが設定されている場合はデフォルトで貪欲ではなくなり、疑問符を付けることで貪欲にすることが出来ます。つまり、デフォルトの仕様を反転します。 括弧で囲んだサブパターンに1より大きい最小繰り返し回数、または最大繰り返し回数の量指定子を適用した場合、最小または最大のサイズに比例して、コンパイルされたパターンに必要なメモリの量が増えます。 アトミックグループと独占的量指定子 繰り返しの最大化と最小化の両方で後に続くものが失敗すると、通常は繰り返す項目の再評価が行われ、異なる繰り返し回数で残りのパターンがマッチするかどうかを調べます。パターンの作成者がマッチを続行する必要が無いと判断した場合、この処理を中止、またはマッチの性質を変更するか早めにマッチを失敗させるのも有効的です。 例えば \d+foo のパターンを 123456bar の対象文字列に適用した場合を考えてみます。6桁の数字にマッチした後"foo"にマッチしなかった場合、5桁のみを使用して\d+へのマッチが再試行され、次に4桁、と順に試行されて結局失敗します。「アトミックグループ」(Jeffrey Fried氏の著書から引用)は、サブパターンがマッチした後にこのような再評価を行わないように指定します。 先ほどの例にアトミックグループを使用した場合、最初に"foo"のマッチに失敗した時点ですぐにマッチが中断されます。表記方法は次のような(?>で始まる特殊な括弧を使用します。 (?>\d+)foo この括弧で囲まれたパターン内の部分は一度マッチすると「ロック」され、そのパターンのマッチに再び失敗してもロックされたパターンへのバックトラックは発生しません。このパターンよりも前の項目へのバックトラックは正常に機能します。 言い換えると、このタイプのサブパターンは、対象文字列の現在のポイントに固定されている場合、同一のスタンドアローンパターンがマッチする文字列にマッチします。 アトミックグループサブパターンはキャプチャ用サブパターンではありません。上記の例のような単純な場合では、できるだけ多くのものを包含するための最大の繰り返し回数と考えることが出来ます。そこで、\d+ 及び \d+は残りのパターンがマッチするように、それらがマッチする桁数を調整しますが、(?>\d+) は一連の数字全体にのみマッチします。 一般にアトミックグループには複雑なサブパターンを任意に含むことが出来、ネストすることも可能です。しかし、アトミックグループのサブパターンが上記の例のように単一の繰り返し項目である場合、「独占的量指定子」と呼ばれる簡単な表記法を使用することが出来ます。独占的量指定子は、量指定子の後に+文字を追加します。この表記法を使って先ほどの例を書き直すと \d++foo となります。独占的量指定子は常に貪欲で、PCRE_UNGREEDYオプションの設定は無視されます。アトミックグループの簡略表記として便利ですが、独占的量指定子と、それと同等なアトミックグループの間に意味や処理上の違いはありません。 パターン内のサブパターンに無制限の繰り返しが含まれていて、さらにそのサブパターン自身も無制限に繰り返しできる場合に、非常に長い時間がかかってしまうマッチの失敗を回避する唯一の方法はアトミックグループを使うことです。 (\D+|<\d+>)*[!?] のパターンは、! か?が後に続く数字以外の文字、または<>で囲まれた数字から成る無限の数のサブストリングとマッチします。マッチすると短時間で処理されます。しかし、それが aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa に適用された場合、失敗を報告するまでに長い時間がかかります。文字列が内部の\D+の繰り返しと外部の * の繰り返しの間で多くの方法で分割されることがあり、それらを全て試行する必要があるからです(例では末尾に単一文字ではなく[!?]を使用しています。これは、単一文字が設定された場合はPCREの最適化によってマッチが早期に失敗する為です。マッチに必要な最後の一文字が記憶され、それが文字列内に無いと失敗します。)。次のように、アトミックグループを使用するようにパターンを変更すると、 ((?>\D+)|<\d+>)*[!?] 数字以外のシーケンスは分割できず、早期に失敗します。 後方参照 文字クラスの外では、0(または複数桁の数字)よりも大きな数字が続くバックスラッシュは、その値と同じだけのキャプチャ用左括弧がその前にある場合に限り、パターン内にある前方(左側のキャプチャ用サブパターン)に対する後方参照になります。 ただし、バックスラッシュに続く10進数が10未満の場合は、常に後方参照として解釈されます。パターン全体にそれと同数のキャプチャ用左括弧が無い場合のみエラーが発生します。つまり、10未満の場合は参照される括弧は左側になくても構いません。バックスラッシュに続く数字の処理についての詳細は上記「印刷不可能な文字」の項目をご覧ください。 後方参照は、サブパターン自体にマッチするものではなく、現在の対象文字列内のキャプチャ用サブパターンに実際にマッチするものにマッチします。 (sens|respons)e and \1ibility のパターンは"sense and sensibility"及び"response and responsibility"にマッチしますが、"sense and responsibility"にはマッチしません。後方参照で大文字と小文字を区別したマッチを行う場合、大文字と小文字が関わってきます。例えば、 ((?i)rah)\s+\1 は"rah rah"、及び"RAH RAH"にマッチしますが、元のキャプチャ用サブパターンが大文字と小文字の区別なくマッチするのにも関わらず"RAH rah"にはマッチしません。 名前の付いたサブパターンへの後方参照はPython構文(?P=name)を使用します。上記の例は次のように書き換えることが出来ます。 (?(?i)rah)\s+(?P=p1) 同じサブパターンに対する後方参照が複数存在する場合があります。サブパターンが特定のマッチに実際に使用されなかった場合、そのサブパターンへの後方参照は常に失敗します。例えば、 (a|(bc))\2 のパターンが"bc"ではなく"a"からマッチを開始した場合は常に失敗します。パターン内には多数のキャプチャ用括弧が存在する場合がある為、バックスラッシュに続く全ての数字は潜在的な後方参照用番号の一部として処理されます。パターンに数字が続く場合、後方参照を終了する為にデリミタを置く必要があります。PCRE_EXTENDEDオプションが設定されている場合は空白を、それ以外の場合は空のコメントを使用することが出来ます。 括弧内での後方参照は、サブパターンを最初に使用した時点で失敗します。例えば(a\1)はマッチしません。しかし、繰り返されるサブパターン内ではこのような参照が便利な場合もあります。例えば、 (a|b\1)+ のパターンは任意の数の"a"、"aba"、"ababbaa"等にマッチします。サブパターンを繰り返すたびに、後方参照は前の繰り返しに対応した文字列にマッチします。この処理が正しく行われるためには、最初の繰り返しが後方参照にマッチする必要が無いパターンを作成する必要があります。これは、上記の例のように選択肢を使用するか、最小値が0の量指定子を指定することで可能です。 言明 言明は、現在のマッチポイントに後続または先行する文字に対するテストで、実際には文字を消費しません。\b、\B、\A、\G、\Z、\z、^、$としてコーディングされる単純な言明については上記をご覧ください。 より複雑な言明はサブパターンとしてコーディングします。対象文字列内の前方を調べるものと、後方を調べるものの2種類があります。現在のマッチ位置が変更されないという点を除いて、言明サブパターンは通常の方法でマッチされます。 言明サブパターンはキャプチャ用サブパターンではありません。また、同じことを繰り返し言明しても意味が無いため、繰り返されません。言明の内部にキャプチャ用サブパターンが含まれている場合、それらはパターン全体内のキャプチャ用サブパターンに番号を割り振るためであると考えられます。しかし、サブストリングのキャプチャは否定の言明では意味が無いため、肯定の言明のみ実行されます。 先読み言明 先読み言明は、肯定の言明では(?= で、否定の言明では(?! で始まります。例えば、 \w+(?=;) は、セミコロンが後続する語にマッチしますが、セミコロンはマッチに含まれません。また foo(?!bar) は、"bar"が後続しないいずれの"foo"にもマッチします。一見似たようなパターンの (?!foo)bar は、"foo"以外が先行する"bar"を見つけるのではなく、続く3文字が"bar"である場合言明(?!foo)は常に真であるため、全ての"bar"を見つけます。その他の効果を得るには後読み言明を使用する必要があります。. パターン内のある位置でマッチを失敗させたい場合、最も簡単な方法は(?!)の使用です。空の文字列は常にマッチするため、空の文字列が存在していないことが必要な言明は常に失敗するからです。 後読み言明 後読み言明は、肯定の言明では(?<=で、否定の言明では(?<!で始まります。例えば、 (?<!foo)bar は、"foo"が先行しない全ての"bar"を見つけます。後読み言明の内容は、マッチする全ての文字列が固定長でなければならないという制限があります。ただし、選択肢が複数ある場合は全てが同じ固定長でなくても構いません。従って (?<=bullock|donkey) は可能ですが、 (?<!dogs?|cats?) はエラーになります。異なる長さの文字列にマッチする選択肢は、後読み言明の最上位でのみ可能です。 (?<=ab(c|de)) のような言明は、最上位にある単一の選択肢が2つの異なる長さにマッチすることがあるため不可能ですが、2つの最上位の選択肢を使って次のように書き直せば使うことが出来ます。 (?<=abc|abde) 後読み言明を実行すると、それぞれの選択肢が一時的に固定幅の分だけ後方に移動してからマッチが試行されます。現在位置の前に十分な文字が無い場合、マッチは失敗します。 PCREでは、後方の長さを計算できなくなるため、後読み言明に\Cエスケープは使えません。異なるバイト数にマッチする\Xエスケープも使用できません。 後読み言明とアトミックグループを併用して、文字列の末尾で効果的にマッチを指定することが出来ます。次のような単純なパターン abcd$ をマッチしない長い文字列に適用した場合を考えてみましょう。マッチは左から右に処理されるため、PCREは対象の文字列内で各"a"を検索してから後続の文字列が残りのパターンとマッチするかどうかを調べます。パターンが次のように指定されている場合、 ^.*abcd$ 最初の .* はまず文字列全体とマッチし、それが失敗した場合(後続する"a"が無いため)、バックトラックを行い最後の文字を除く全ての文字、次に最後の2文字を除く全ての文字、と順にマッチが試行されます。その後、文字列全体に対して右から左へ再度"a"が検索されるため、この処理は意味がありません。ただし、パターンを ^(?>.*)(?<=abcd) のように書き換えるか、次のように同等な独占的量指定子構文を使用すると ^.*+(?<=abcd) .*に対するバックトラックは行われず、文字列全体にのみマッチ出来ます。以降の後読み言明では、最後の4文字に関するテストが一回だけ行われます。失敗した場合、マッチはすぐにエラーになります。文字列が長い場合はこの方法によって処理時間を大幅に削減することが出来ます。 多重言明の使用 複数の言明(任意の種類の)を連続して使用する場合があります。例えば、 (?<=\d{3})(?<!999)foo は"999"ではない3桁の数字が先行する"foo"にマッチします。各言明は対象文字列内の同じ位置で、それぞれ独立して適用される点に注意してください。最初に前の3文字が全て数字であるかどうかチェックが行われ、次にその3桁が"999"ではないかどうかのチェックが行われます。このパターンは"foo"の前に6文字あり、その最初の複数の文字が数字で最後の3文字が"999"ではない場合、マッチしません。例えば"123abc-foo"にはマッチしません。これに一致するパターンは次の通りです。 (?<=\d{3}...)(?<!999)foo この場合、最初の言明が先行の6文字を検索し、最初の3文字が数字であることをチェックし、次に2番目の言明がその数字が"999"ではないことをチェックします。 言明は任意の組み合わせでネストすることが出来ます。例えば、 (?<=(?<!foo)bar)baz は、"foo"に先行されていない"baz"が前にある"baz"にマッチします。一方、 (?<=\d{3}(?!999)...)foo は"999"ではない3桁の数字、または3文字が前にある"foo"にマッチする別のパターンです。 条件付きサブパターン 言明の結果、または前回のキャプチャ用サブパターンがマッチしたかどうかに応じて、マッチの処理を条件付きでサブパターンに従わせること、または2つのサブパターンのいずれかを選択することができます。条件付きサブパターンの形式には次の2つがあります。 (?(condition)yes-pattern) (?(condition)yes-pattern|no-pattern) 条件が満たされている場合はyes-patternが使用され、そうでない場合はno-pattern(存在すれば)が使用されます。サブパターン内に3つ以上の選択肢がある場合は、コンパイル時エラーが発生します。 条件は3種類あります。括弧内のテキストが数字のシーケンスである場合、この数字に対応するキャプチャ用サブパターンが以前にマッチしていれば条件が満たされます。数字は0より大きい必要があります。次のパターンを見てみましょう。読みやすくするため(PCRE_EXTENDEDオプションが設定されていると想定)、また解説しやすいように3分割するため特に意味のない空白が挿入されています。 ( \( )? [^()]+ (?(1) \) ) 最初の部分は任意の開き括弧にマッチします。この文字が存在する場合はそれを最初のキャプチャ用サブストリングとして設定します。2番目の部分は括弧以外の1つ以上の文字にマッチします。3番目の部分は最初の括弧のセットがマッチしたかどうかテストする条件付きサブパターンです。マッチした場合、つまり対象文字列が開き括弧で始まっていた場合、条件は真でyes-patternが実行され、閉じ括弧が要求されます。そうでない場合、no-patternが存在しないためサブパターンがマッチするものはありません。つまり、このパターンは括弧以外のシーケンスにマッチし、括弧に囲まれているかどうかは任意です。 条件が文字列(R)の場合、パターンまたはサブパターンに対する再帰呼び出しが行われた場合に条件が満たされます。「最上位」では、条件は偽になります。 条件が数字か(R)のシーケンスではない場合は言明でなければなりません。肯定または否定の先読み、或いは後読み言明を使うことが出来ます。次のパターンを見てみましょう。特に意味のない空白を含み、2行目には2つの選択肢があります。 (?(?=[^a-z]*[a-z]) \d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} ) 条件は、1文字が後に続く文字以外の任意のシーケンスにマッチする肯定の先読み言明です。つまり、対象文字列内に少なくとも1つの文字があるかどうかをテストします。文字が見つかった場合、対象の文字列は最初の選択肢にマッチします。そうでない場合は2番目の選択肢にマッチします。このパターンはdd-aaa-ddかdd-dd-ddの2つの形式の文字列いずれか一方にマッチします。aaa は文字でdd は数字です。
|