mirror of
https://github.com/php/doc-ja.git
synced 2026-03-24 07:02:08 +01:00
2523 lines
118 KiB
XML
2523 lines
118 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
||
<!-- $Revision$ -->
|
||
<!-- splitted from ./ja/functions/pcre.xml, last change in rev 1.1 -->
|
||
<!-- EN-Revision: a0434e05111acabf2b9b2c7847e7e733f8dab0dc Maintainer: takagi Status: ready -->
|
||
<!-- Credits: haruki,hirokawa,mumumu -->
|
||
<chapter xml:id="reference.pcre.pattern.syntax" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||
<title>パターン構文</title>
|
||
<titleabbrev>PCRE 正規表現構文</titleabbrev>
|
||
|
||
<section xml:id="regexp.introduction">
|
||
<title>はじめに</title>
|
||
<para>
|
||
PCRE がサポートする正規表現の構文と意味体系をこのセクションで示します。
|
||
正規表現については、Perl のドキュメントや他の多くの書籍においても
|
||
解説されており、実例が豊富に記載されているものもあります。特に、
|
||
O'Reilly 発刊 Jeffrey Friedl 著 "Mastering Regular Expressions"
|
||
(ISBN 1-56592-257) 〔日本語版:「詳説 正規表現」〕には、
|
||
たいへん詳細に解説されています。
|
||
</para>
|
||
<para>
|
||
以降の説明は、参考文書 (reference documentation) として
|
||
扱われることを想定しています。
|
||
</para>
|
||
<para>
|
||
正規表現は、ある種のパターンであり、検索対象文字列 (subject string)
|
||
に対して左から右〔文字列の初めから終わり〕の順にマッチングが行われます。
|
||
一部の例外を除き、パターン中の文字はその文字自体を表し、
|
||
検索対象文字列内の同じ文字にマッチします。簡単な例をあげると、パターン
|
||
<literallayout>
|
||
The quick brown fox
|
||
</literallayout>
|
||
は、検索対象文字列内にある、このパターンと同一の部分にマッチします。
|
||
</para>
|
||
</section>
|
||
<section xml:id="regexp.reference.delimiters">
|
||
<title>デリミタ</title>
|
||
<para>
|
||
PCRE 関数を使うときには、パターンを
|
||
<emphasis>delimiters</emphasis> で囲まなければなりません。
|
||
英数字、バックスラッシュ、空白文字以外の任意の文字をデリミタとして使うことができます。
|
||
有効なデリミタの前に空白文字を付けても、黙って無視されます。
|
||
</para>
|
||
<para>
|
||
デリミタとしてよく使われる文字は、スラッシュ (<literal>/</literal>)、
|
||
ハッシュ記号 (<literal>#</literal>) およびチルダ (<literal>~</literal>) です。
|
||
次に示す例は、どれも正しいデリミタです。
|
||
<informalexample>
|
||
<programlisting>
|
||
<![CDATA[
|
||
/foo bar/
|
||
#^[^0-9]$#
|
||
+php+
|
||
%[a-zA-Z0-9_-]%
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
<para>
|
||
角括弧形式のデリミタを使うこともできます。
|
||
これは、開き角括弧と閉じ角括弧がそれぞれ開始デリミタ、終了デリミタを表す形式です。
|
||
<literal>()</literal>、
|
||
<literal>{}</literal>、<literal>[]</literal> そして <literal><></literal>
|
||
はどれも、角括弧形式のデリミタとして有効です。
|
||
<informalexample>
|
||
<programlisting>
|
||
<![CDATA[
|
||
(this [is] a (pattern))
|
||
{this [is] a (pattern)}
|
||
[this [is] a (pattern)]
|
||
<this [is] a (pattern)>
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
角括弧形式のデリミタを使う場合は、パターン内でメタ文字を使うときのエスケープは不要です。
|
||
しかし、他のデリミタと同様、(メタ文字としてではなく) リテラルとして扱う場合は、
|
||
エスケープする必要があります。
|
||
</para>
|
||
<para>
|
||
パターンの中でデリミタ文字をマッチさせたい場合は、バックスラッシュでエスケープしなければなりません。
|
||
パターン内でデリミタが頻繁にあらわれる場合は、
|
||
デリミタを別の文字に変更したほうが読みやすくなります。
|
||
<informalexample>
|
||
<programlisting>
|
||
<![CDATA[
|
||
/http:\/\//
|
||
#http://#
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
<function>preg_quote</function> 関数を使うと、パターンに使う文字列をエスケープすることができます。
|
||
オプションの二番目のパラメータで、エスケープするデリミタを指定します。
|
||
</para>
|
||
<para>
|
||
終了デリミタの後に <link linkend="reference.pcre.pattern.modifiers">
|
||
パターン修飾子</link> を付加することもできます。次の例は、大文字小文字を区別しないマッチを行うものです。
|
||
<informalexample>
|
||
<programlisting>
|
||
<![CDATA[
|
||
#[a-z]#i
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
</section>
|
||
<section xml:id="regexp.reference.meta">
|
||
<title>メタ文字</title>
|
||
<para>
|
||
正規表現の強力さは、パターン中に選択肢や繰り返しを記述できることに
|
||
あります。選択肢や繰り返しは、<emphasis>メタ文字</emphasis>
|
||
(meta-character) を使ってパターン中に記述します。メタ文字は、
|
||
その文字自体を表わさず、代わって特別な解釈が行われます。
|
||
</para>
|
||
<para>
|
||
メタ文字には、2 種類あります。ひとつは、角カッコ内を除き、
|
||
パターン中のどこででも使用できる文字です。もうひとつは、
|
||
角カッコで括られた中でだけ使用できる文字です。
|
||
</para>
|
||
<para>
|
||
前者の角カッコ外で使用できるメタ文字には、次のものがあります。
|
||
|
||
<table>
|
||
<title>角カッコ外で使用できるメタ文字</title>
|
||
<tgroup cols="2">
|
||
<thead>
|
||
<row>
|
||
<entry>メタ文字</entry><entry>説明</entry>
|
||
</row>
|
||
</thead>
|
||
<tbody>
|
||
<row>
|
||
<entry>\</entry><entry>多目的に使う一般的なエスケープ文字 </entry>
|
||
</row>
|
||
<row>
|
||
<entry>^</entry><entry>検索対象(複数行モードでは行)の始まりを言明</entry>
|
||
</row>
|
||
<row>
|
||
<entry>$</entry><entry>検索対象の終わりあるいは終端の改行文字の前(複数行モードでは行の終わり)を言明</entry>
|
||
</row>
|
||
<row>
|
||
<entry>.</entry><entry>改行を除くすべての文字にマッチ(デフォルト時)</entry>
|
||
</row>
|
||
<row>
|
||
<entry>[</entry><entry>文字クラス定義の開始</entry>
|
||
</row>
|
||
<row>
|
||
<entry>]</entry><entry>文字クラス定義の終了</entry>
|
||
</row>
|
||
<row>
|
||
<entry>|</entry><entry>選択枝の開始</entry>
|
||
</row>
|
||
<row>
|
||
<entry>(</entry><entry>サブパターンの開始</entry>
|
||
</row>
|
||
<row>
|
||
<entry>)</entry><entry>サブパターンの終了</entry>
|
||
</row>
|
||
<row>
|
||
<entry>?</entry><entry>( の意味を拡張/0 または 1 回マッチ/なるべく少ない回数だけマッチ
|
||
(<link linkend="regexp.reference.repetition">繰り返し</link> を参照)</entry>
|
||
</row>
|
||
<row>
|
||
<entry>*</entry><entry>0 回以上の繰り返し</entry>
|
||
</row>
|
||
<row>
|
||
<entry>+</entry><entry>1 回以上の繰り返し</entry>
|
||
</row>
|
||
<row>
|
||
<entry>{</entry><entry>最小/最大を指定する量指定子の開始</entry>
|
||
</row>
|
||
<row>
|
||
<entry>}</entry><entry>最小/最大を指定する量指定子の終了</entry>
|
||
</row>
|
||
</tbody>
|
||
</tgroup>
|
||
</table>
|
||
|
||
パターン中の角カッコで括まれた部分を「<link linkend="regexp.reference.character-classes">文字クラス</link>」と言います。
|
||
文字クラスで使えるメタ文字は、次のものだけです。
|
||
|
||
<table>
|
||
<title>角カッコ内のメタ文字 (<emphasis>文字クラス</emphasis>)</title>
|
||
<tgroup cols="2">
|
||
<thead>
|
||
<row>
|
||
<entry>Meta-character</entry><entry>Description</entry>
|
||
</row>
|
||
</thead>
|
||
<tbody>
|
||
<row>
|
||
<entry>\</entry><entry>一般的なエスケープ文字</entry>
|
||
</row>
|
||
<row>
|
||
<entry>^</entry><entry>クラスの否定。ただし、文字クラスの最初の文字に用いた場合のみ</entry>
|
||
</row>
|
||
<row>
|
||
<entry>-</entry><entry>文字の範囲の指定</entry>
|
||
</row>
|
||
</tbody>
|
||
</tgroup>
|
||
</table>
|
||
|
||
以降のセクションで、各メタ文字の使用法の説明を行います。
|
||
</para>
|
||
</section>
|
||
|
||
<section xml:id="regexp.reference.escape">
|
||
<title>エスケープシーケンス</title>
|
||
<para>
|
||
バックスラッシュ〔日本語環境では円記号となる場合もある〕には、
|
||
いくつかの使用法があります。ひとつめの使用法は、
|
||
非英数字の前に記述する場合で、続く文字が表す特別な意味を取り去ります。
|
||
このエスケープ文字としての使用法は、
|
||
文字クラスの内外部いずれでも可能です。
|
||
</para>
|
||
<para>
|
||
たとえば、"*" 文字とマッチさせたい場合は、パターンを "\*" と記述します。
|
||
続く文字がメタ文字として解釈されるものであるかには関係ありませんので、
|
||
いかなる非英数字に対しても、"\" を付けると、その文字自体が
|
||
表わされることになります。特に、
|
||
バックスラッシュとマッチさせたい場合は、"\\" と記述します。
|
||
</para>
|
||
<note>
|
||
<para>
|
||
シングルクォートあるいはダブルクォートで囲まれた PHP の
|
||
<link linkend="language.types.string.syntax">文字列</link>
|
||
の中では、バックスラッシュは特別な意味を表します。
|
||
そのため、正規表現 \\ を使用して \ とマッチさせたい場合は
|
||
PHP のコード内では "\\\\" あるいは '\\\\' と記述する必要があります。
|
||
</para>
|
||
</note>
|
||
<para>
|
||
パターンを、
|
||
<link linkend="reference.pcre.pattern.modifiers">PCRE_EXTENDED</link>
|
||
オプションを付けてコンパイルすると、(文字クラス内部を除き)
|
||
パターン中の空白文字、および "#" とその次の改行文字との間の文字は
|
||
無視されます。空白文字や "#" をパターン中に含めるには、
|
||
バックスラッシュを用いてエスケープします。
|
||
</para>
|
||
<para>
|
||
バックスラッシュの 2 番目の使用法は、非表示文字〔制御コードなど〕を
|
||
パターン中に目に見える形で記述するための方法です。ヌル文字は
|
||
パターンを終了させてしまうため使えませんが、その他の非表示文字は、
|
||
パターンにそのまま含めても問題はありません。しかし、パターンの編集には、
|
||
バイナリ文字をそのまま用いるよりも、以下に示すエスケープシーケンスを
|
||
用いる方が便利でしょう。
|
||
</para>
|
||
<para>
|
||
<variablelist>
|
||
<varlistentry>
|
||
<term><emphasis>\a</emphasis></term>
|
||
<listitem>
|
||
<simpara>アラーム、ベル文字 (16進 07)</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\cx</emphasis></term>
|
||
<listitem>
|
||
<simpara>"control-x", ここで x は任意の文字</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\e</emphasis></term>
|
||
<listitem>
|
||
<simpara>エスケープ文字 (16進 1B)</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\f</emphasis></term>
|
||
<listitem>
|
||
<simpara>改ページ (formfeed) (16進 0C)</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\n</emphasis></term>
|
||
<listitem>
|
||
<simpara>改行 (newline) (16進 0A)</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\p{xx}</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
xx プロパティを持つ文字、詳細は
|
||
<link linkend="regexp.reference.unicode">unicode プロパティ</link>
|
||
を参照
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\P{xx}</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
xx プロパティを持たない文字、詳細は
|
||
<link linkend="regexp.reference.unicode">unicode プロパティ</link>
|
||
を参照
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\r</emphasis></term>
|
||
<listitem>
|
||
<simpara>復帰 (carriage return) (16進 0D)</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\R</emphasis></term>
|
||
<listitem>
|
||
<simpara>改行: \n、\r、\r\n にマッチする</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\t</emphasis></term>
|
||
<listitem>
|
||
<simpara>タブ (16進 09)</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\xhh</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
16 進コードで hh の文字
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\ddd</emphasis></term>
|
||
<listitem>
|
||
<simpara>8 進コードで ddd の文字、もしくは、後方参照</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
</variablelist>
|
||
</para>
|
||
<para>
|
||
"<literal>\cx</literal>" の正確な働きは、次の通りです。
|
||
"<literal>x</literal>" が小文字の場合、
|
||
大文字に変換されます。続いて、文字の 6 ビット目 (16進数 40) が
|
||
反転されます。つまり、"<literal>\cz</literal>" は 16 進数の 1A になり、
|
||
"<literal>\c{</literal>" は 3B になり、
|
||
"<literal>\c;</literal>" は 7B になります。
|
||
</para>
|
||
<para>
|
||
"<literal>\x</literal>" の後では、2 桁までの 16 進数が読まれます
|
||
(大小文字どちらも可能です)。
|
||
<emphasis>UTF-8 モード</emphasis> では、
|
||
"<literal>\x{...}</literal>" という記法も使えます。
|
||
この場合、波括弧の中身は16進数を示す文字列です。
|
||
この文字列は、16進数の数値でコードポイントを表す UTF-8 文字として解釈されます。
|
||
オリジナルの16進のエスケープシーケンス <literal>\xhh</literal> は、
|
||
値が127より大きい場合、2バイトのUTF-8 文字とマッチします。
|
||
</para>
|
||
<para>
|
||
"\0" の後では、さらに 2 桁の 8 進数が
|
||
読みこまれます。いずれの場合も、2 桁より少ない場合、桁があるだけ
|
||
読みこまれます。つまり、"<literal>\0\x\07</literal>" は
|
||
ヌル文字 2 つの後にベル文字が
|
||
続いたものを表します。8 進数を指定する場合は、必ず最初のゼロに続いて
|
||
残りの 2 桁の数字を指定するように注意してください。
|
||
</para>
|
||
<para>
|
||
バックスラッシュの後に 0 以外の数字が続く場合の処理は複雑です。
|
||
文字クラスの外部では、 PCRE は、続く数字全体を 10 進数として読みます。
|
||
数字が 10 よりも小さい場合、または、正規表現の中に含まれる
|
||
キャプチャ用左カッコの数以下の場合、
|
||
<emphasis>後方参照</emphasis> として解釈されます。
|
||
この動作に関する詳しい説明は、後ほど、カッコによるサブパターンの説明を
|
||
行ってから示します
|
||
</para>
|
||
<para>
|
||
文字クラスの中、または、指定された 10 進数が 9 より大きく、
|
||
キャプチャ用サブパターンの数がこの数に満たない場合は、PCRE は
|
||
バックスラッシュの後から最大 3 文字の 8 進数を再度読みこみ、
|
||
その値の最下位 8 ビットから 1 バイトを生成します。
|
||
その後に続く数字は、それ自体を表します。以下に例を示します。
|
||
</para>
|
||
<para>
|
||
<variablelist>
|
||
<varlistentry>
|
||
<term><emphasis>\040</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
スペースの別の表記法
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\40</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
上と同じ。ただし、キャプチャ用サブパターンが 40 個未満の場合
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\7</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
常に後方参照
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\11</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
後方参照、または、タブの別記法
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\011</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
常にタブ
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\0113</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
タブの後に文字 "3" が続いたもの
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\113</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
8進コードで 113 の文字
|
||
(99 を超える後方参照は存在しないため)
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\377</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
全ビットが 1 である 1 バイト
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\81</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
後方参照、または、ヌル文字の後に 2つの文字
|
||
"8" および "1" が続いたもの
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
</variablelist>
|
||
</para>
|
||
<para>
|
||
3 桁を超えて 8 進数は読みこまれないため、100 以上の 8 進数には
|
||
ゼロを前につけてはいけないことに注意してください。
|
||
</para>
|
||
<para>
|
||
これらの 1 バイト値を定義するエスケープシーケンスは、
|
||
文字クラスの内外部のいずれでも使用できます。加えて、文字クラス内では
|
||
エスケープシーケンス "<literal>\b</literal>" はバックスペース (16進 08) として解釈されます。
|
||
文字クラス外では、別の意味を有します(別記参照)。
|
||
</para>
|
||
<para>
|
||
バックスラッシュの第 3 の使用法は、包括的な文字型を指定する用途です。
|
||
</para>
|
||
<para>
|
||
<variablelist>
|
||
<varlistentry>
|
||
<term><emphasis>\d</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
10 進数字
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\D</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
10 進数字でない文字
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\h</emphasis></term>
|
||
<listitem><simpara>水平方向の空白文字</simpara></listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\H</emphasis></term>
|
||
<listitem><simpara>水平方向の空白文字でない文字</simpara></listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\s</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
空白文字
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\S</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
空白文字でない文字
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\v</emphasis></term>
|
||
<listitem><simpara>垂直方向の空白文字</simpara></listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\V</emphasis></term>
|
||
<listitem><simpara>垂直方向の空白文字でない文字</simpara></listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\w</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
単語構成文字 (word character)
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\W</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
非単語構成文字 (non-word character)
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
</variablelist>
|
||
</para>
|
||
<para>
|
||
これらエスケープシーケンスの各組により、文字集合が 2 つに分割されます。
|
||
文字は、各組のどちらか片方だけにマッチします。
|
||
</para>
|
||
<para>
|
||
空白文字とは HT (9)、LF (10)、FF (12)、CR (13)、スペース (32) のことです。
|
||
しかし、ロケールを指定したマッチングを行った場合には、
|
||
128から255までのコードポイントの文字
|
||
(たとえば NBSP (A0)) も空白文字とみなされる可能性があります。
|
||
</para>
|
||
<para>
|
||
単語構成文字とは、英字または数字またはアンダースコア文字であり、Perl
|
||
が定義するところの「単語」と成り得る文字のことです。文字および数字の
|
||
定義は、PCRE の文字テーブルにより制御され、ロケールを指定して
|
||
マッチングを行うと変わる可能性があります。
|
||
例えば、"fr" (フランス語)ロケールの場合、128 を超える
|
||
文字コードのいくつかは、アクセント付きの文字に使われており、
|
||
これらは <literal>\w</literal> とマッチします。
|
||
</para>
|
||
<para>
|
||
これらの文字型表記は、文字クラスの内外によらず使用可能で、
|
||
対応する型のたかだか 1 文字とマッチします。現在のマッチング位置が
|
||
検索対象文字列の終端である場合、マッチできる文字が無いので、
|
||
マッチは失敗します。
|
||
</para>
|
||
<para>
|
||
バックスラッシュの第 4 の使用法は、簡単な言明 (assertion) です。
|
||
言明とは、マッチがある特定の位置でだけ可能だという条件を指定するもので、
|
||
検索対象文字列から文字を消費 (consume)〔つまり文字自体にマッチ〕
|
||
しません。サブパターンを使ったより複雑な言明の方法もありますが、
|
||
それについての解説は後ほど行います。バックスラッシュを使った言明は、
|
||
次のものがあります
|
||
</para>
|
||
<para>
|
||
<variablelist>
|
||
<varlistentry>
|
||
<term><emphasis>\b</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
単語境界
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\B</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
非単語境界
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\A</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
検索対象文字列の始端(複数行モードとは独立)
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\Z</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
検索対象文字列の終端、または終端の改行(複数行モードとは独立)
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\z</emphasis></term>
|
||
<listitem>
|
||
<simpara>
|
||
検索対象文字列の終端(複数行モードとは独立)
|
||
</simpara>
|
||
</listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\G</emphasis></term>
|
||
<listitem><simpara>マッチングの開始位置</simpara></listitem>
|
||
</varlistentry>
|
||
</variablelist>
|
||
</para>
|
||
<para>
|
||
これらの言明は、文字クラス内では使用できません(また、文字クラス内では、
|
||
"<literal>\b</literal>" はバックスペース文字という別の意味を持つので
|
||
注意してください)。
|
||
</para>
|
||
<para>
|
||
単語境界 (word boundary) とは、検索対象文字列において、
|
||
カレントの文字およびその前の文字が同時に <literal>\w</literal>
|
||
もしくは <literal>\W</literal> にマッチしない(すなわち、片方が
|
||
<literal>\w</literal> にマッチし、もう片方が <literal>\W</literal>
|
||
にマッチする)位置、もしくは、文字列の始めか終わりで、
|
||
その始めか終わりの文字が <literal>\w</literal> にマッチする位置の
|
||
ことです。
|
||
</para>
|
||
<para>
|
||
言明 <literal>\A</literal>, <literal>\Z</literal>,
|
||
<literal>\z</literal> は、(<link linkend="regexp.reference.anchors">アンカー</link> で説明する)ハット記号やドル記号とは
|
||
異なり、オプション設定によらず、文字列の始端または終端だけに
|
||
マッチします。これらの言明は、<link
|
||
linkend="reference.pcre.pattern.modifiers">PCRE_MULTILINE</link> および <link
|
||
linkend="reference.pcre.pattern.modifiers">PCRE_DOLLAR_ENDONLY</link>
|
||
オプションの影響を受けません。
|
||
<literal>\Z</literal> と <literal>\z</literal> との違いは、
|
||
<literal>\Z</literal> は文字列の末尾の改行の前の位置および文字列の
|
||
終端にマッチするのに対し、<literal>\z</literal> は文字列の終端にのみ
|
||
マッチすることです。
|
||
</para>
|
||
<para>
|
||
言明 <literal>\G</literal> は、カレントのマッチング位置が、
|
||
<function>preg_match</function> 関数の <parameter>offset</parameter>
|
||
引数に指定されたマッチングの開始位置である場合に真になります。
|
||
<parameter>offset</parameter> が非ゼロの場合は、<literal>\A</literal>
|
||
と等価ではありません。
|
||
</para>
|
||
|
||
<para>
|
||
<literal>\Q</literal> と <literal>\E</literal> とを使って、
|
||
パターン中のメタ文字を無視させることができます。
|
||
たとえば、
|
||
<literal>\w+\Q.$.\E$</literal>
|
||
は、文字列の終端において1つ以上の単語構成文字のあとに <literal>.$.</literal>
|
||
というリテラルが続いたものにマッチします。
|
||
|
||
これらは、デリミタの動作を変更しないことに注意して下さい。
|
||
たとえば、<literal>#\Q#\E#$</literal> は無効なパターンです。
|
||
なぜなら、<literal>#</literal> がパターンの終端としてマークされ、
|
||
<literal>\E#</literal> が無効な修正子と解釈されるからです。
|
||
</para>
|
||
|
||
<para>
|
||
<literal>\K</literal> を使用すると、マッチの開始位置をリセットできます。
|
||
たとえば、パターン
|
||
<literal>foo\Kbar</literal> は "foobar" にマッチしますが、
|
||
結果は "bar" にマッチしたと報告されます。
|
||
<literal>\K</literal> を使用しても、キャプチャした部分文字列には影響を及ぼしません。
|
||
たとえば、パターン <literal>(foo)\Kbar</literal> が
|
||
"foobar" にマッチしたときの最初の部分文字列は "foo" です。
|
||
</para>
|
||
|
||
</section>
|
||
|
||
<section xml:id="regexp.reference.unicode">
|
||
<title>Unicode 文字プロパティ</title>
|
||
<para>
|
||
PHP 5.1.0 以降、<emphasis>UTF-8 モード</emphasis> を設定した場合に、
|
||
一般的な文字タイプにマッチする新たなエスケープシーケンスが 3 つ追加されました。
|
||
</para>
|
||
<variablelist>
|
||
<varlistentry>
|
||
<term><emphasis>\p{xx}</emphasis></term>
|
||
<listitem><simpara>xx プロパティを持つ文字</simpara></listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\P{xx}</emphasis></term>
|
||
<listitem><simpara>xx プロパティを持たない文字</simpara></listitem>
|
||
</varlistentry>
|
||
<varlistentry>
|
||
<term><emphasis>\X</emphasis></term>
|
||
<listitem><simpara>拡張 Unicode シーケンス</simpara></listitem>
|
||
</varlistentry>
|
||
</variablelist>
|
||
<para>
|
||
ここで <literal>xx</literal> で表されているプロパティ名は、Unicode で
|
||
一般カテゴリプロパティ (general category properties) として規定されているものに
|
||
なります。すべての文字は、いずれかひとつのプロパティを持ちます。
|
||
プロパティは、2 文字の略語で表されます。Perl と同じく、
|
||
開き波カッコとプロパティ名との間にハット文字を記述することで否定を指定できます。
|
||
たとえば、<literal>\p{^Lu}</literal> は <literal>\P{Lu}</literal> と同じです。
|
||
</para>
|
||
<para>
|
||
<literal>\p</literal> もしくは <literal>\P</literal> の後に、一文字だけを記述すると
|
||
その文字で始まるすべてのプロパティが指定されたことになります。
|
||
この場合、否定の指定をしていない場合、波カッコを使用しなくても構いません。
|
||
以下の 2 つの例は等価になります。
|
||
</para>
|
||
<informalexample>
|
||
<programlisting>
|
||
<![CDATA[
|
||
\p{L}
|
||
\pL
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
<table>
|
||
<title>使用可能なプロパティコード</title>
|
||
<tgroup cols="3">
|
||
<thead>
|
||
<row>
|
||
<entry>プロパティ</entry>
|
||
<entry>マッチ</entry>
|
||
<entry>備考</entry>
|
||
</row>
|
||
</thead>
|
||
<tbody>
|
||
<row>
|
||
<entry><literal>C</literal></entry>
|
||
<entry>その他 (Other)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Cc</literal></entry>
|
||
<entry>コントロール文字 (Control)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Cf</literal></entry>
|
||
<entry>非可視整形用文字 (Format)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Cn</literal></entry>
|
||
<entry>未定義コードポイント (Unassigned)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Co</literal></entry>
|
||
<entry>私的利用領域 (Private use)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row rowsep="1">
|
||
<entry><literal>Cs</literal></entry>
|
||
<entry>サロゲート (Surrogate)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>L</literal></entry>
|
||
<entry>アルファベット (Letter)</entry>
|
||
<entry>
|
||
<literal>Ll</literal>、
|
||
<literal>Lm</literal>、<literal>Lo</literal>、<literal>Lt</literal> および
|
||
<literal>Lu</literal> を含む
|
||
</entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Ll</literal></entry>
|
||
<entry>小文字アルファベット (Lower case letter)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Lm</literal></entry>
|
||
<entry>擬似文字 (Modifier letter)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Lo</literal></entry>
|
||
<entry>その他の文字 (Other letter)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Lt</literal></entry>
|
||
<entry>タイトル文字 (Title case letter)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row rowsep="1">
|
||
<entry><literal>Lu</literal></entry>
|
||
<entry>大文字アルファベット (Upper case letter)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>M</literal></entry>
|
||
<entry>記号 (Mark)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Mc</literal></entry>
|
||
<entry>修飾文字 (Spacing mark)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Me</literal></entry>
|
||
<entry>他の文字を囲むための文字 (Enclosing mark)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row rowsep="1">
|
||
<entry><literal>Mn</literal></entry>
|
||
<entry>他の文字を修飾するための文字 (Non-spacing mark)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>N</literal></entry>
|
||
<entry>数字 (Number)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Nd</literal></entry>
|
||
<entry>10 進数字 (Decimal number)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Nl</literal></entry>
|
||
<entry>数値を表す文字 (Letter number)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row rowsep="1">
|
||
<entry><literal>No</literal></entry>
|
||
<entry>その他の数字 (Other number)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>P</literal></entry>
|
||
<entry>句読記号 (Punctuation)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Pc</literal></entry>
|
||
<entry>連結用句読記号 (Connector punctuation)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Pd</literal></entry>
|
||
<entry>ダッシュ (Dash punctuation)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Pe</literal></entry>
|
||
<entry>閉じ句読記号 (Close punctuation)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Pf</literal></entry>
|
||
<entry>末尾句読記号 (Final punctuation)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Pi</literal></entry>
|
||
<entry>先頭句読記号 (Initial punctuation)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Po</literal></entry>
|
||
<entry>その他の句読記号 (Other punctuation)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row rowsep="1">
|
||
<entry><literal>Ps</literal></entry>
|
||
<entry>開き句読記号 (Open punctuation)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>S</literal></entry>
|
||
<entry>記号 (Symbol)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Sc</literal></entry>
|
||
<entry>通貨記号 (Currency symbol)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Sk</literal></entry>
|
||
<entry>合わせ文字 (Modifier symbol)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Sm</literal></entry>
|
||
<entry>数学記号 (Mathematical symbol)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row rowsep="1">
|
||
<entry><literal>So</literal></entry>
|
||
<entry>その他の記号 (Other symbol)</entry>
|
||
<entry>絵文字(emoji)も含みます</entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Z</literal></entry>
|
||
<entry>区切り文字 (Separator)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Zl</literal></entry>
|
||
<entry>行区切り文字 (Line separator)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Zp</literal></entry>
|
||
<entry>段落区切り文字 (Paragraph separator)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Zs</literal></entry>
|
||
<entry>空白文字 (Space separator)</entry>
|
||
<entry></entry>
|
||
</row>
|
||
</tbody>
|
||
</tgroup>
|
||
</table>
|
||
<para>
|
||
<literal>InMusicalSymbols</literal> のような拡張プロパティ (extended properties)
|
||
を、PCRE はサポートしていません。
|
||
</para>
|
||
<para>
|
||
大小文字を区別しないマッチングを設定していても、これらのエスケープ
|
||
シーケンスには影響しません。たとえば、<literal>\p{Lu}</literal> は
|
||
常に大文字にのみマッチします。
|
||
</para>
|
||
<para>
|
||
Unicode の文字は、何らかのスクリプトに属するものとして定義されています。
|
||
スクリプト名を指定すれば、そのスクリプトの文字群の一文字にマッチさせることができます。
|
||
たとえば、次のように使います。
|
||
</para>
|
||
<itemizedlist>
|
||
<listitem>
|
||
<simpara><literal>\p{Greek}</literal></simpara>
|
||
</listitem>
|
||
<listitem>
|
||
<simpara><literal>\P{Han}</literal></simpara>
|
||
</listitem>
|
||
</itemizedlist>
|
||
<para>
|
||
どのスクリプトにも属しない文字は、ぜんぶまとめて
|
||
<literal>Common</literal> で表します。現在サポートするスクリプトは次のとおりです。
|
||
</para>
|
||
<table>
|
||
<title>サポートするスクリプト</title>
|
||
<tgroup cols="5">
|
||
<tbody>
|
||
<row>
|
||
<entry><literal>Arabic</literal></entry>
|
||
<entry><literal>Armenian</literal></entry>
|
||
<entry><literal>Avestan</literal></entry>
|
||
<entry><literal>Balinese</literal></entry>
|
||
<entry><literal>Bamum</literal></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Batak</literal></entry>
|
||
<entry><literal>Bengali</literal></entry>
|
||
<entry><literal>Bopomofo</literal></entry>
|
||
<entry><literal>Brahmi</literal></entry>
|
||
<entry><literal>Braille</literal></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Buginese</literal></entry>
|
||
<entry><literal>Buhid</literal></entry>
|
||
<entry><literal>Canadian_Aboriginal</literal></entry>
|
||
<entry><literal>Carian</literal></entry>
|
||
<entry><literal>Chakma</literal></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Cham</literal></entry>
|
||
<entry><literal>Cherokee</literal></entry>
|
||
<entry><literal>Common</literal></entry>
|
||
<entry><literal>Coptic</literal></entry>
|
||
<entry><literal>Cuneiform</literal></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Cypriot</literal></entry>
|
||
<entry><literal>Cyrillic</literal></entry>
|
||
<entry><literal>Deseret</literal></entry>
|
||
<entry><literal>Devanagari</literal></entry>
|
||
<entry><literal>Egyptian_Hieroglyphs</literal></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Ethiopic</literal></entry>
|
||
<entry><literal>Georgian</literal></entry>
|
||
<entry><literal>Glagolitic</literal></entry>
|
||
<entry><literal>Gothic</literal></entry>
|
||
<entry><literal>Greek</literal></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Gujarati</literal></entry>
|
||
<entry><literal>Gurmukhi</literal></entry>
|
||
<entry><literal>Han</literal></entry>
|
||
<entry><literal>Hangul</literal></entry>
|
||
<entry><literal>Hanunoo</literal></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Hebrew</literal></entry>
|
||
<entry><literal>Hiragana</literal></entry>
|
||
<entry><literal>Imperial_Aramaic</literal></entry>
|
||
<entry><literal>Inherited</literal></entry>
|
||
<entry><literal>Inscriptional_Pahlavi</literal></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Inscriptional_Parthian</literal></entry>
|
||
<entry><literal>Javanese</literal></entry>
|
||
<entry><literal>Kaithi</literal></entry>
|
||
<entry><literal>Kannada</literal></entry>
|
||
<entry><literal>Katakana</literal></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Kayah_Li</literal></entry>
|
||
<entry><literal>Kharoshthi</literal></entry>
|
||
<entry><literal>Khmer</literal></entry>
|
||
<entry><literal>Lao</literal></entry>
|
||
<entry><literal>Latin</literal></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Lepcha</literal></entry>
|
||
<entry><literal>Limbu</literal></entry>
|
||
<entry><literal>Linear_B</literal></entry>
|
||
<entry><literal>Lisu</literal></entry>
|
||
<entry><literal>Lycian</literal></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Lydian</literal></entry>
|
||
<entry><literal>Malayalam</literal></entry>
|
||
<entry><literal>Mandaic</literal></entry>
|
||
<entry><literal>Meetei_Mayek</literal></entry>
|
||
<entry><literal>Meroitic_Cursive</literal></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Meroitic_Hieroglyphs</literal></entry>
|
||
<entry><literal>Miao</literal></entry>
|
||
<entry><literal>Mongolian</literal></entry>
|
||
<entry><literal>Myanmar</literal></entry>
|
||
<entry><literal>New_Tai_Lue</literal></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Nko</literal></entry>
|
||
<entry><literal>Ogham</literal></entry>
|
||
<entry><literal>Old_Italic</literal></entry>
|
||
<entry><literal>Old_Persian</literal></entry>
|
||
<entry><literal>Old_South_Arabian</literal></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Old_Turkic</literal></entry>
|
||
<entry><literal>Ol_Chiki</literal></entry>
|
||
<entry><literal>Oriya</literal></entry>
|
||
<entry><literal>Osmanya</literal></entry>
|
||
<entry><literal>Phags_Pa</literal></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Phoenician</literal></entry>
|
||
<entry><literal>Rejang</literal></entry>
|
||
<entry><literal>Runic</literal></entry>
|
||
<entry><literal>Samaritan</literal></entry>
|
||
<entry><literal>Saurashtra</literal></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Sharada</literal></entry>
|
||
<entry><literal>Shavian</literal></entry>
|
||
<entry><literal>Sinhala</literal></entry>
|
||
<entry><literal>Sora_Sompeng</literal></entry>
|
||
<entry><literal>Sundanese</literal></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Syloti_Nagri</literal></entry>
|
||
<entry><literal>Syriac</literal></entry>
|
||
<entry><literal>Tagalog</literal></entry>
|
||
<entry><literal>Tagbanwa</literal></entry>
|
||
<entry><literal>Tai_Le</literal></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Tai_Tham</literal></entry>
|
||
<entry><literal>Tai_Viet</literal></entry>
|
||
<entry><literal>Takri</literal></entry>
|
||
<entry><literal>Tamil</literal></entry>
|
||
<entry><literal>Telugu</literal></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Thaana</literal></entry>
|
||
<entry><literal>Thai</literal></entry>
|
||
<entry><literal>Tibetan</literal></entry>
|
||
<entry><literal>Tifinagh</literal></entry>
|
||
<entry><literal>Ugaritic</literal></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>Vai</literal></entry>
|
||
<entry><literal>Yi</literal></entry>
|
||
<entry />
|
||
<entry />
|
||
<entry />
|
||
</row>
|
||
</tbody>
|
||
</tgroup>
|
||
</table>
|
||
<para>
|
||
<literal>\X</literal> は、Unicode 拡張書記素クラスタにマッチします。
|
||
拡張書記素クラスタとは、ひとつあるいは複数の Unicode 文字の組み合わせで単一のグリフを構成するものです。
|
||
事実上、これは Unicode 版の <literal>.</literal> だと考えてかまいません。
|
||
その文字をレンダリングするために実際に何文字が使われているかは考えずに、ひとつの合成文字に対応します。
|
||
</para>
|
||
<para>
|
||
8.32 より古いバージョンの PCRE (これは、組み込みの PCRE ライブラリを使っている場合には PHP 5.4.14 より前のバージョンにあたります) では、
|
||
<literal>\X</literal> は <literal>(?>\PM\pM*)</literal> と等価です。
|
||
つまり、記号 (mark) プロパティの付いていない文字と、その後に続く 0 以上の
|
||
記号プロパティ付きの文字にマッチし、その並びをアトミック (atomic) な
|
||
まとまりとして取り扱います。記号プロパティ付きの文字とは、アクセント記号などの
|
||
直前の文字に対して影響するようなもののことです。
|
||
</para>
|
||
<para>
|
||
Unicode プロパティを使った文字列マッチングは速くありません。PCRE は
|
||
15,000 以上のデータからなるデータ構造を検索する必要が有るためです。
|
||
そのため、PCRE では、<literal>\d</literal> や <literal>\w</literal> といった
|
||
以前から有るエスケープシーケンスは Unicode プロパティを使用しないように
|
||
なっています。
|
||
</para>
|
||
</section>
|
||
|
||
<section xml:id="regexp.reference.anchors">
|
||
<title>アンカー</title>
|
||
<para>
|
||
ハット記号 (<literal>^</literal>) は、文字クラス外でマッチモード (matching mode) がデフォルトの場合、
|
||
カレントのマッチング位置が対象文字列の始端である場合に真だ
|
||
という言明です。文字クラス内では、ハット記号 (<literal>^</literal>) はまったく別の意味と
|
||
なります(別記参照)。
|
||
</para>
|
||
<para>
|
||
パターン中で選択肢を用いる場合は、ハット記号 (<literal>^</literal>) は、それが必要な選択肢の
|
||
先頭に記述すればよく、パターン全体の先頭にしか記述できない訳では
|
||
ありません。すべての選択肢がハット記号 (<literal>^</literal>) で始まる場合、つまり
|
||
パターンが対象文字列の始端でのみマッチするように制限されている
|
||
パターンは、固定 (anchored) パターンと呼ばれます(もちろん、
|
||
他にもパターンを固定にする方法はあります)。
|
||
</para>
|
||
<para>
|
||
ドル記号 (<literal>$</literal>) は、(デフォルトでは)カレントのマッチング位置が
|
||
対象文字列の終端にあるか、文字列の終わりの改行文字の直前にある場合に
|
||
真だという言明です。パターン中で選択肢を用いる場合は、ドル記号 (<literal>$</literal>) は、
|
||
必要な選択肢の最後に記述すればよく、パターン全体の最後にしか
|
||
記述できない訳ではありません。
|
||
ドル記号は、文字クラス内では特別な意味を持ちません。
|
||
</para>
|
||
<para>
|
||
コンパイル時またはマッチング時に <link
|
||
linkend="reference.pcre.pattern.modifiers">PCRE_DOLLAR_ENDONLY</link>
|
||
オプションを設定すると、ドル記号の動作を文字列の終端でのみ
|
||
マッチするように変更することができます
|
||
このオプションは \Z 言明には影響しません。
|
||
</para>
|
||
<para>
|
||
ハット記号とドル記号の動作は、<link
|
||
linkend="reference.pcre.pattern.modifiers">PCRE_MULTILINE</link>
|
||
オプションを設定すると変化します。この場合、対象文字列の始端および
|
||
終端にマッチするのに加えて、対象文字列の "\n" 文字の直前および直後に
|
||
それぞれマッチします。例えば、パターン /^abc$/ は、複数行モードに
|
||
おいては、対象文字列 "def\nabc" にマッチしますが、
|
||
複数行モードでない場合はマッチしません。すなわち、すべての選択肢が
|
||
"^" で始まっており単一行モードでは固定のパターンも、複数行モードでは
|
||
固定パターンでなくなります。<link
|
||
linkend="reference.pcre.pattern.modifiers">PCRE_DOLLAR_ENDONLY</link>
|
||
オプションは、 <link
|
||
linkend="reference.pcre.pattern.modifiers">PCRE_MULTILINE</link>
|
||
オプションが設定されている場合は無視されます。
|
||
</para>
|
||
<para>
|
||
どちらのモードでも、エスケープシーケンス \A, \Z, \z は、
|
||
対象文字列の始端および終端にマッチすることに注意してください。ですので、
|
||
パターン中の選択肢がすべて \A で始まる場合、<link
|
||
linkend="reference.pcre.pattern.modifiers">PCRE_MULTILINE</link>
|
||
オプションの設定によらず、そのパターンは固定となります。
|
||
</para>
|
||
</section>
|
||
|
||
<section xml:id="regexp.reference.dot">
|
||
<title>ドット</title>
|
||
<para>
|
||
パターン中のドット(ピリオド、終止符)は、文字クラス外では、
|
||
対象文字列の任意の 1 文字にマッチします。非出力文字も含まれます。
|
||
ただし、(デフォルトでは)改行文字とはマッチしません。
|
||
<link linkend="reference.pcre.pattern.modifiers">PCRE_DOTALL</link>
|
||
オプションを設定すると、ドットは改行にもマッチするようになります。
|
||
ドットの処理は、ハット記号およびドル記号とは完全に独立しています。
|
||
共通な点は共に改行文字と関連することだけです。ドットは、
|
||
文字クラス内では特別な意味を持ちません。
|
||
</para>
|
||
<para>
|
||
<emphasis>\C</emphasis> は単一バイトの文字にマッチします。
|
||
これは、<emphasis>UTF-8 モード</emphasis> で、ドットが複数バイトの文字にも
|
||
マッチするような場合に有用です。
|
||
</para>
|
||
</section>
|
||
|
||
<section xml:id="regexp.reference.character-classes">
|
||
<title>文字クラス</title>
|
||
<para>
|
||
開き角カッコは文字クラス (character class) の開始を表し、
|
||
閉じ角カッコにより文字クラスは終了します。閉じ角カッコだけでは、
|
||
特別な意味を持ちません。閉じ角カッコを文字クラスのメンバとしたい場合は、
|
||
文字クラスの最初の文字(否定のハット記号がある場合はその直後)とするか、
|
||
バックスラッシュでエスケープする必要があります。
|
||
</para>
|
||
<para>
|
||
文字クラスは、検索対象文字列のたかだか 1 文字にマッチします。
|
||
マッチする文字は、その文字クラスによって定義された文字集合のうちの
|
||
どれかです。ただし、文字クラスの最初の文字がハット記号の場合は、
|
||
マッチする文字は、その文字クラスに定義されていない文字となります。
|
||
ハット記号自体をクラスのメンバとしたい場合は、文字クラスの
|
||
最初の文字としないか、バックスラッシュでエスケープしてください。
|
||
</para>
|
||
<para>
|
||
例えば、文字クラス [aeiou] は小文字の母音にマッチしますが、[^aeiou] は
|
||
小文字の母音以外の文字にマッチします。ハット記号は、含まれない文字を
|
||
列挙することにより文字クラスに含まれる文字を指定するための簡略表記です。
|
||
文字クラスは、言明ではありません。対象文字列から文字を消費します。また、
|
||
カレントのポインタが文字列の終端にある場合には、マッチに失敗します。
|
||
</para>
|
||
<para>
|
||
大小文字を区別しないマッチングを行うよう設定した場合は、
|
||
クラス内の文字は大小文字の両方を表します。例えば、
|
||
大小文字を区別しない場合、[aeiou] は "a" にも "A" にもマッチします。
|
||
同じく大小文字を区別しない場合 [^aeiou] は "A" にマッチしませんが、
|
||
区別する場合はマッチします
|
||
</para>
|
||
<para>
|
||
<link linkend="reference.pcre.pattern.modifiers">PCRE_DOTALL</link>
|
||
または <link
|
||
linkend="reference.pcre.pattern.modifiers">PCRE_MULTILINE</link>
|
||
オプションをどのように設定しようとも、改行文字は、文字クラスにおいて
|
||
特別な扱いはされません。たとえば、 [^a] のようなクラスは、
|
||
常に改行にマッチします。
|
||
</para>
|
||
<para>
|
||
マイナス (ハイフン) 記号は、文字クラスで文字の範囲を指定するために
|
||
使われます。例えば、[d-m] は d と m の間のあらゆる文字にマッチします。
|
||
マイナス記号が文字クラス内に必要な場合は、バックスラッシュで
|
||
エスケープしてください。もしくは、文字クラスの最初または最後など、
|
||
範囲を示すと解釈されない場所に記述してください。
|
||
</para>
|
||
<para>
|
||
文字リテラル "]" を、文字範囲を示す最後の文字として使うことは
|
||
できません。 [W-]46] というパターンは、2 つの文字 ("W" および"-") が
|
||
含まれるクラスの後に文字列リテラル "46]" が続いていると解釈され、
|
||
"W46]" や "-46]" にマッチします。しかし、"]" をバックスラッシュで
|
||
エスケープすると文字範囲の終端として解釈され、 [W-]46] は、
|
||
範囲指定の後に 2 つの文字が続く 1 つのクラスとして解釈されます。
|
||
"]" の 8 進あるいは 16 進表現も文字範囲の終端として使用可能です。
|
||
</para>
|
||
<para>
|
||
文字範囲指定では、ASCII 照合順序 (collating sequence) が用いられます
|
||
〔つまり、範囲指定する際の文字の並び順として ASCII が用いられます〕。
|
||
[\000-\037] のような、数値的な文字の指定も使用可能です。大小文字を
|
||
区別しないマッチングを行うよう設定した場合、パターン中の英字は
|
||
大小文字の両方にマッチします。例えば、[W-c] は、[][\^_`wxyzabc] に
|
||
等価であり、大小文字に関係なくマッチします。また、 "fr"
|
||
ロケールの文字テーブルを使う場合、[\xc8-\xcb] は、
|
||
大小文字の区別無くアクセント付きの E にマッチします。
|
||
</para>
|
||
<para>
|
||
文字型 \d, \D, \s, \S, \w, \W も、文字クラス内で使え、
|
||
マッチする文字を追加することが可能です。例えば、[ABCDEF] は、
|
||
16進数にマッチします。ハット記号と大文字の文字型を組み合わせることで、
|
||
小文字の文字型がマッチするものより狭い文字集合を
|
||
簡便に指定することができます。例えば、クラス [^\W_] は、
|
||
〔単語構成〕文字および数字にマッチしますが、アンダースコアには
|
||
マッチしません。
|
||
</para>
|
||
<para>
|
||
\, -, (始端の)^ および終端の ] 以外のすべての非英数字は、
|
||
文字クラスにおいて特別な意味を持たない文字ですが、
|
||
エスケープしても問題はありません。
|
||
パターンの終端文字は常に特別扱いされるので、
|
||
正規表現内で私用する場合は必ずエスケープしなければなりません。
|
||
</para>
|
||
<para>
|
||
Perl は、POSIX 記法の文字クラスもサポートしています。これは、
|
||
<literal>[:</literal> と <literal>:]</literal> で囲んだ名前を角カッコ内で使うものです。
|
||
PCRE でもこの記法に対応しています。たとえば <literal>[01[:alpha:]%]</literal> は
|
||
"0"、"1"、任意のアルファベット、あるいは "%" にマッチします。対応しているクラス名は次のとおりです。
|
||
<table>
|
||
<title>文字クラス</title>
|
||
<tgroup cols="2">
|
||
<tbody>
|
||
<row><entry><literal>alnum</literal></entry><entry>letters and digits</entry></row>
|
||
<row><entry><literal>alpha</literal></entry><entry>letters</entry></row>
|
||
<row><entry><literal>ascii</literal></entry><entry>character codes 0 - 127</entry></row>
|
||
<row><entry><literal>blank</literal></entry><entry>space or tab only</entry></row>
|
||
<row><entry><literal>cntrl</literal></entry><entry>control characters</entry></row>
|
||
<row><entry><literal>digit</literal></entry><entry>decimal digits (same as \d)</entry></row>
|
||
<row><entry><literal>graph</literal></entry><entry>printing characters, excluding space</entry></row>
|
||
<row><entry><literal>lower</literal></entry><entry>lower case letters</entry></row>
|
||
<row><entry><literal>print</literal></entry><entry>printing characters, including space</entry></row>
|
||
<row><entry><literal>punct</literal></entry><entry>printing characters, excluding letters and digits</entry></row>
|
||
<row><entry><literal>space</literal></entry><entry>white space (not quite the same as \s)</entry></row>
|
||
<row><entry><literal>upper</literal></entry><entry>upper case letters</entry></row>
|
||
<row><entry><literal>word</literal></entry><entry>"word" characters (same as \w)</entry></row>
|
||
<row><entry><literal>xdigit</literal></entry><entry>hexadecimal digits</entry></row>
|
||
</tbody>
|
||
</tgroup>
|
||
</table>
|
||
<literal>space</literal> 文字は HT (9), LF (10), VT (11), FF (12), CR (13),
|
||
およびスペース (32) です。この中に VT 文字 (コード 11) が含まれていることに注目しましょう。
|
||
この点で、"space" は <literal>\s</literal> と異なります。こちらは VT を含みません
|
||
(Perl との互換性のため)。
|
||
</para>
|
||
<para>
|
||
<literal>word</literal> は Perl 拡張で、<literal>blank</literal> は Perl 5.8
|
||
からの GNU 拡張です。それ以外の Perl 拡張には否定があります。否定を指示するには
|
||
<literal>^</literal> をコロンの後に続けます。たとえば
|
||
<literal>[12[:^digit:]]</literal> は "1"、"2"、あるいは任意の非数値にマッチします。
|
||
</para>
|
||
<para>
|
||
UTF-8 モードでは、128 より大きなコードはどの POSIX 文字クラスにもマッチしません。
|
||
libpcre 8.10 以降では、
|
||
いくつかの文字クラスが Unicode 文字プロパティを使うように変わりました。
|
||
それらの文字クラスでは、ここに挙げた制約はあてはまりません。
|
||
詳細は、<link xlink:href="&url.pcre.man;">PCRE(3) のマニュアル</link>
|
||
を参照ください。
|
||
</para>
|
||
<para>
|
||
Unicode 文字プロパティは、文字クラスに含めることができます。
|
||
しかし、範囲指定に含めることはできません。
|
||
マイナス (ハイフン) を Unicode 文字クラスの後に続けた場合は、その文字としてマッチします。
|
||
範囲指定を Unicode 文字プロパティで終えようとすると、警告が発生します。
|
||
</para>
|
||
</section>
|
||
|
||
<section xml:id="regexp.reference.alternation">
|
||
<title>選択肢</title>
|
||
<para>
|
||
縦線は、パターンに選択肢 (alternative) を列挙するために使われます。
|
||
例えば、パターン <literal>gilbert|sullivan</literal>
|
||
は、"gilbert" または "sullivan" にマッチします。
|
||
選択肢の数に制限はありません。また、空の選択肢も可能です
|
||
(空の文字列にマッチします)。マッチの手順としては、
|
||
各選択肢が左から右に順にマッチするかどうか試行され、
|
||
最初にマッチに成功した選択肢が使われます。選択肢を(後述する)
|
||
サブパターン内に記述した場合、マッチの「成功」とは、
|
||
サブパターン内の選択肢も、メインのパターンの他の部分もマッチした
|
||
ということを意味します。
|
||
</para>
|
||
<para>
|
||
どの選択肢がマッチしたかを、
|
||
<literal>(*MARK:NAME)</literal> や <literal>(*:NAME)</literal>
|
||
の形式で記録することができます。
|
||
<literal>(*MARK)</literal> のような動詞の形式は、
|
||
いくつでも記述でき、名前はユニークである必要がありません。
|
||
マッチが成功すると、最後に現れた
|
||
<literal>(*MARK:NAME)</literal> の名前が
|
||
あたかも <literal>MARK</literal>
|
||
と呼ばれるキャプチャグループが存在するかのように、
|
||
マッチした情報の一部として置かれます。
|
||
よって、この情報は <function>preg_match</function> の
|
||
<parameter>matches</parameter> から読み取ることができ、
|
||
<function>preg_replace_callback</function> の
|
||
<parameter>callback</parameter> に渡すことなどができます。
|
||
</para>
|
||
</section>
|
||
|
||
<section xml:id="regexp.reference.internal-options">
|
||
<title>内部オプション設定</title>
|
||
<para>
|
||
<link linkend="reference.pcre.pattern.modifiers">PCRE_CASELESS</link>,
|
||
<link linkend="reference.pcre.pattern.modifiers">PCRE_MULTILINE</link>,
|
||
<link linkend="reference.pcre.pattern.modifiers">PCRE_DOTALL</link>
|
||
<link linkend="reference.pcre.pattern.modifiers">PCRE_UNGREEDY</link>,
|
||
<link linkend="reference.pcre.pattern.modifiers">PCRE_EXTRA</link>,
|
||
<link linkend="reference.pcre.pattern.modifiers">PCRE_EXTENDED</link>
|
||
および PCRE_DUPNAMES
|
||
オプションの設定は、パターン中で変更できます。これには、Perl
|
||
オプション文字を "(?" と ")" とで括った並びを用います。
|
||
オプション文字には以下のものがあります。
|
||
|
||
<table>
|
||
<title>内部オプション文字</title>
|
||
<tgroup cols="2">
|
||
<tbody>
|
||
<row>
|
||
<entry><literal>i</literal></entry>
|
||
<entry><link linkend="reference.pcre.pattern.modifiers">PCRE_CASELESS</link></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>m</literal></entry>
|
||
<entry><link linkend="reference.pcre.pattern.modifiers">PCRE_MULTILINE</link></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>s</literal></entry>
|
||
<entry><link linkend="reference.pcre.pattern.modifiers">PCRE_DOTALL</link></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>x</literal></entry>
|
||
<entry><link linkend="reference.pcre.pattern.modifiers">PCRE_EXTENDED</link></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>U</literal></entry>
|
||
<entry><link linkend="reference.pcre.pattern.modifiers">PCRE_UNGREEDY</link></entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>X</literal></entry>
|
||
<entry><link linkend="reference.pcre.pattern.modifiers">PCRE_EXTRA</link> (PHP 7.3.0 以降はサポートされません) </entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>J</literal></entry>
|
||
<entry><link linkend="reference.pcre.pattern.modifiers">PCRE_INFO_JCHANGED</link></entry>
|
||
</row>
|
||
</tbody>
|
||
</tgroup>
|
||
</table>
|
||
</para>
|
||
<para>
|
||
例えば、(?im) は、大小文字を区別しない、複数行モードのマッチングを
|
||
設定します。ハイフンを前につけることにより、そのオプションを
|
||
解除することも可能です。 (?im-sx) のように設定と解除とを
|
||
組み合わせることも可能です。この場合、<link
|
||
linkend="reference.pcre.pattern.modifiers">PCRE_CASELESS</link> と
|
||
<link linkend="reference.pcre.pattern.modifiers">PCRE_MULTILINE</link>
|
||
とが設定され、<link
|
||
linkend="reference.pcre.pattern.modifiers">PCRE_DOTALL</link> と
|
||
<link linkend="reference.pcre.pattern.modifiers">PCRE_EXTENDED</link>
|
||
とが解除されます。
|
||
オプション文字がハイフンの前にも後にも指定された場合、
|
||
そのオプションは解除されます。
|
||
</para>
|
||
<para>
|
||
オプションの変更がトップレベル(つまりサブパターンのカッコの外)で行われた場合、
|
||
その変更はパターンの後ろの部分に適用されます。
|
||
パターン <literal>/ab(?i)c/</literal> は "abc" および "abC" にマッチします。
|
||
</para>
|
||
<para>
|
||
サブパターンの内部でオプションの変更を行った場合は、
|
||
その効果は違ったものになります。この動作変更は、Perl 5.005
|
||
で行われました。サブパターン中のオプション変更は、そのサブパターンの
|
||
設定が行われた場所以降の部分にのみ影響します。そのため、パターン
|
||
|
||
<literal>(a(?i)b)c</literal>
|
||
|
||
は、"abc" および "aBc" にマッチし、他の文字列にはマッチしません
|
||
(<link linkend="reference.pcre.pattern.modifiers">PCRE_CASELESS</link>
|
||
が設定されていないと仮定)。このように、パターンの各場所に
|
||
異なった設定を行うようなオプション指定が可能です。
|
||
ある選択肢に行われた設定変更は、同じサブパターン中の後に続く選択肢に
|
||
波及します。例えば、パターン
|
||
|
||
<literal>(a(?i)b|c)</literal>
|
||
|
||
は、"ab", "aB", "c", "C" にマッチします。"C" にマッチする場合を
|
||
見てみると、オプション設定が行われている最初の選択肢は
|
||
マッチせずに捨てられてしまっています。それでも、オプションの設定は
|
||
行われ "C" にマッチします。これは、オプション設定の効果が
|
||
コンパイル時に生じることによります。さもないと、
|
||
非常に奇妙な動作をするかもしれません。
|
||
</para>
|
||
<para>
|
||
PCRE 特有のオプション <link
|
||
linkend="reference.pcre.pattern.modifiers">PCRE_UNGREEDY</link>
|
||
および <link
|
||
linkend="reference.pcre.pattern.modifiers">PCRE_EXTRA</link> は、
|
||
それぞれ文字 U および X を用いて、Perl 互換のオプションと同様に
|
||
変更することが可能です。 (?X) フラグの設定は特別で、最上位においても、
|
||
パターン中で他の設定を有効にする前に指定する必要があります。
|
||
このフラグは、最初に指定するのが最善です。
|
||
</para>
|
||
</section>
|
||
|
||
<section xml:id="regexp.reference.subpatterns">
|
||
<title>サブパターン</title>
|
||
<para>
|
||
サブパターンは、丸カッコで括られたパターンのことで、ネストも可能です。
|
||
パターンの一部をサブパターンにすると、以下の 2 つのことが可能になります。
|
||
</para>
|
||
<orderedlist>
|
||
<listitem>
|
||
<para>
|
||
選択肢の範囲の指定 (localize)。例えば、パターン
|
||
<literal>cat(aract|erpillar|)</literal>
|
||
は、単語 "cat", "cataract", "caterpillar" にマッチします。
|
||
カッコをつけないと、このパターンは、"cataract", "erpillar"
|
||
または空の文字列にマッチしてしまいます。
|
||
</para>
|
||
</listitem>
|
||
<listitem>
|
||
<para>
|
||
サブパターンによる値の取得(キャプチャ)。
|
||
パターン全体としてマッチに成功した場合、対象文字列の内、
|
||
サブパターンにマッチした部分の値がコールした側に
|
||
(<function>pcre_exec</function> の引数 <emphasis>ovector</emphasis> で)
|
||
返されます。
|
||
開きカッコの数が(1 から始まって)左から右に数えられ、
|
||
キャプチャ用サブパターン (capturing subpattern) の番号が指定されます。
|
||
</para>
|
||
</listitem>
|
||
</orderedlist>
|
||
<para>
|
||
例えば、文字列 "the red king" に対し、パターン
|
||
|
||
<literallayout>
|
||
the ((red|white) (king|queen))
|
||
</literallayout>
|
||
|
||
をマッチングさせた場合、キャプチャされる部分文字列は、
|
||
"red king", "red", "king" であり、
|
||
それぞれ 1 番, 2 番, 3 番と番号がふられます。
|
||
</para>
|
||
<para>
|
||
カッコに 2 つの機能があるということが、いつも良い方に働くわけでは
|
||
ありません。値をキャプチャする必要はないが、グループ分けのために
|
||
サブパターンを複数用いたい場合も少なくありません。開きカッコの後に
|
||
"?:" を付けると、そのサブパターンは値のキャプチャを行わず、
|
||
キャプチャ用サブパターンの番号としてもカウントされません。例えば、
|
||
文字列 "the white queen" に対し、次のパターンをマッチングさせてみましょう。
|
||
|
||
<literallayout>
|
||
the ((?:red|white) (king|queen))
|
||
</literallayout>
|
||
|
||
キャプチャされる部分文字列は、"white queen" と "queen" であり、
|
||
それぞれ 1 番と 2 番に番号付けされます。キャプチャ可能な部分文字列の
|
||
数は最大で 65535 までです。
|
||
そんな大量のパターンをコンパイルするのはそもそも無理かもしれませんが、
|
||
そのあたりは libpcre の configure 時のオプションしだいです。
|
||
</para>
|
||
<para>
|
||
簡略形として、値のキャプチャをしないサブパターンの先頭で
|
||
オプションの設定をする場合、オプションの文字を "?" と ":"
|
||
の間に入れることができます。つまり、次の 2 つのパターン、
|
||
</para>
|
||
|
||
<informalexample>
|
||
<programlisting>
|
||
<![CDATA[
|
||
(?i:saturday|sunday)
|
||
(?:(?i)saturday|sunday)
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
|
||
<para>
|
||
は、まったく同じ文字列集合にマッチします。
|
||
選択肢は左から右に試行され、オプションはサブパターンの終端に達するまで
|
||
リセットされないので、ある選択枝にあるオプション設定は後に続く
|
||
選択枝にも作用します。このため、上のパターンは、"Saturday" と同様に
|
||
"SUNDAY" にもマッチします
|
||
</para>
|
||
|
||
<para>
|
||
<literal>(?P<name>pattern)</literal> という記法を用いて
|
||
サブパターンに名前をつけることができます。
|
||
このサブパターンにマッチした部分は、マッチ時に返される配列内で
|
||
通常どおりの数値添字によるアクセスだけでなく名前でもアクセスできるようになります。
|
||
二通りの別の構文
|
||
<literal>(?<name>pattern)</literal> および <literal>(?'name'pattern)</literal>
|
||
も用意されています。
|
||
</para>
|
||
|
||
<para>
|
||
複数の条件にマッチさせたいときに、
|
||
ひとつの正規表現の中でサブグループを切り替えなければならないこともあります。
|
||
通常は、たとえその中のいずれかひとつにしかマッチしなかったとしても
|
||
それぞれに個別の後方参照番号が振られます。
|
||
これを解決するために使えるのが <literal>(?|</literal> 構文で、
|
||
重複した番号を振ることができるようになります。
|
||
次の正規表現で文字列
|
||
<literal>Sunday</literal> をマッチングするとどうなるでしょうか。
|
||
</para>
|
||
|
||
<informalexample>
|
||
<programlisting>
|
||
<![CDATA[(?:(Sat)ur|(Sun))day]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
|
||
<para>
|
||
<literal>Sun</literal> が後方参照 2 に格納され、
|
||
後方参照 1 は空となります。
|
||
<literal>Saturday</literal> にマッチした場合は
|
||
後方参照 1 に存在する <literal>Sat</literal> に入り、
|
||
後方参照 2 は存在しません。
|
||
この問題を解決するには、パターンを変更して
|
||
<literal>(?|</literal> を使うようにします。
|
||
</para>
|
||
|
||
<informalexample>
|
||
<programlisting>
|
||
<![CDATA[(?|(Sat)ur|(Sun))day]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
|
||
<para>
|
||
このパターンを使えば、<literal>Sun</literal> と <literal>Sat</literal>
|
||
の両方が後方参照 1 に格納されます。
|
||
</para>
|
||
</section>
|
||
|
||
<section xml:id="regexp.reference.repetition">
|
||
<title>繰り返し</title>
|
||
<para>
|
||
繰り返し (repetition) は、量指定子 (quantifier) を使って指定します。
|
||
量指定子は、以下の要素の後に付けることが出来ます。
|
||
|
||
<itemizedlist>
|
||
<listitem><simpara>個々の文字。エスケープされた文字も含む</simpara></listitem>
|
||
<listitem><simpara>メタ文字 . (ドット) </simpara></listitem>
|
||
<listitem><simpara>文字クラス </simpara></listitem>
|
||
<listitem><simpara>後方参照 (次のセクションを参照) </simpara></listitem>
|
||
<listitem><simpara>カッコで括られたサブパターン(言明は除く - 別記参照)</simpara></listitem>
|
||
</itemizedlist>
|
||
</para>
|
||
<para>
|
||
汎用の量指定子 (general repetition quantifier) は、波カッコの中に
|
||
2 つの数をカンマで区切って記述したもので、マッチ可能な
|
||
最小と最大の繰り返し数を指定します。ただし、65536 以上の数は
|
||
指定できません。さらに、最初の数は 2 番目の数以下である必要があります。
|
||
例えば、パターン
|
||
|
||
<literallayout>
|
||
z{2,4}
|
||
</literallayout>
|
||
|
||
は、"zz", "zzz", "zzzz" にマッチします。閉じ波カッコだけでは
|
||
特別な意味を持ちません。カンマを残したまま 2 番目の数だけを省略すると、
|
||
繰り返しの上限が設定されません。 2 番目の数字とカンマの両方を省略すると、
|
||
必要なマッチの数を過不足なく指定できます。つまり、
|
||
|
||
<literallayout>
|
||
[aeiou]{3,}
|
||
</literallayout>
|
||
|
||
は、最短で 3 回母音が連続するものにマッチし、
|
||
もっと多く連続する場合にもマッチします。一方、
|
||
|
||
<literallayout>
|
||
\d{8}
|
||
</literallayout>
|
||
|
||
は、ぴったり 8 桁の数字にのみマッチします。
|
||
|
||
</para>
|
||
<simpara>
|
||
PHP 8.4.0 より前のバージョンでは、開き波カッコは、
|
||
量指定子を置けない場所、つまり量指定子の構文に適合しない場所に
|
||
記述された場合、文字リテラルとして解釈されます。例えば、
|
||
<literal>{,6}</literal> は量指定子ではなく、4つの文字からなる文字列リテラルとなります。
|
||
|
||
PHP 8.4.0 以降では、PCRE 拡張モジュールに PCRE2 ライブラリのバージョン 10.44 がバンドルされています。
|
||
このバージョンでは <literal>\d{,8}</literal> のようなパターンが書けるようになり、
|
||
<literal>\d{0,8}</literal> と同じ意味になります。
|
||
|
||
更に、PHP 8.4.0 以降では、
|
||
<literal>\d{0 , 8}</literal> や <literal>\d{ 0 , 8 }</literal> のように
|
||
量指定子の開き波カッコの周りに空白文字を入れることができます。
|
||
</simpara>
|
||
<para>
|
||
{0} という量指定子の指定も可能です。
|
||
直前の項目および量指定子が存在しないという指定になります。
|
||
</para>
|
||
<para>
|
||
簡単(および歴史的な互換性)のため、よく使われる 3 つの量指定子には、
|
||
次のような 1 文字の省略型があります。
|
||
|
||
<table>
|
||
<title>単一文字の量指定子</title>
|
||
<tgroup cols="2">
|
||
<tbody>
|
||
<row>
|
||
<entry><literal>*</literal></entry>
|
||
<entry><literal>{0,}</literal> と同じ </entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>+</literal></entry>
|
||
<entry><literal>{1,}</literal> と同じ </entry>
|
||
</row>
|
||
<row>
|
||
<entry><literal>?</literal></entry>
|
||
<entry><literal>{0,1}</literal> と同じ </entry>
|
||
</row>
|
||
</tbody>
|
||
</tgroup>
|
||
</table>
|
||
</para>
|
||
<para>
|
||
たとえば
|
||
|
||
<literallayout>
|
||
(a?)*
|
||
</literallayout>
|
||
|
||
の様に、「文字無し」にマッチし得るサブパターンの後ろに
|
||
上限指定の無い量指定子を記述すると、無限ループができてしまう可能性が
|
||
あります。
|
||
</para>
|
||
<para>
|
||
以前のバージョンの Perl および PCRE は、このようなパターンに関して
|
||
コンパイル時にエラーを発生していました。しかし、有用な場合もあるので、
|
||
現在はこのようなパターンも許可されています。ただし、
|
||
繰り返しが指定されたサブパターンが文字無しにマッチすると、
|
||
ループは強制的に中断されます。
|
||
</para>
|
||
<para>
|
||
デフォルトでは、量指定子は「貪欲 (greedy)」です。つまり、
|
||
残りのパターンが失敗しない限りにおいて、(許可された回数の上限まで)
|
||
出来るだけ多くマッチします。 この動作が問題を生じる場合もあります。
|
||
そのよく知られた例としては、 C プログラムのコメントに
|
||
マッチさせようとする場合が挙げられます。 /* と */ との間が
|
||
コメントですが、コメント中にも文字 * や / が現れる可能性があります。
|
||
そこで、C のコメントにマッチさせようとして、パターン
|
||
|
||
<literallayout>
|
||
/\*.*\*/
|
||
</literallayout>
|
||
|
||
を使って、文字列
|
||
|
||
<literallayout>
|
||
/* first comment */ not comment /* second comment */
|
||
</literallayout>
|
||
|
||
に対して、マッチングを行うと、文字列全体にマッチしてしまい上手く行きません。
|
||
.* 要素が貪欲であるためです。
|
||
</para>
|
||
<para>
|
||
しかし、量指定子の後に疑問符を付けると、貪欲さは消え、
|
||
できるだけ少ない回数だけマッチします。このため、パターン
|
||
|
||
<literallayout>
|
||
/\*.*?\*/
|
||
</literallayout>
|
||
|
||
は、C コメントに正しくマッチします。量指定子の他の意味は変化せず、
|
||
マッチの回数だけが変更されます。疑問符のこの使用法と、
|
||
量指定子としての使用法とを混同しないようにしてください。
|
||
このように疑問符には 2 種類の使用法があるため、
|
||
|
||
<literallayout>
|
||
\d??\d
|
||
</literallayout>
|
||
|
||
のように 2 重に使うこともできます。
|
||
このパターンは、可能であれば 1 桁の数字にマッチします。
|
||
パターンの残り部分がそうでないとマッチできない場合に限り、
|
||
2 桁の数字にもマッチします。
|
||
</para>
|
||
<para>
|
||
<link linkend="reference.pcre.pattern.modifiers">PCRE_UNGREEDY</link>
|
||
オプション(Perl ではこのオプションは利用できません)を設定すると、
|
||
量指定子は、デフォルトで貪欲でなくなり、
|
||
各量指定子の後ろに疑問符をつけてはじめて貪欲になります。言いかえると、
|
||
疑問符のデフォルトの動作を逆転します。
|
||
</para>
|
||
<para>
|
||
量指定子の後ろに <literal>+</literal> を記述すると「独占的 (possessive)」
|
||
になります。可能なだけ多くの文字を取り込み、パターンの残りの部分のマッチの際に
|
||
取り込んだ文字を戻すことはしません。したがって、パターン <literal>.*abc</literal>
|
||
は "aabc" にマッチしますが、<literal>.*+abc</literal> はマッチしません。
|
||
これは、<literal>.*+</literal> が対象文字列のすべてを取り込んでしまうためです。
|
||
独占的量指定子を使って処理速度を向上させることができます。
|
||
</para>
|
||
<para>
|
||
カッコを使ったサブパターンに、最小の繰り返し回数(1 以上)や
|
||
最大の繰り返し回数を指定した場合、その繰り返し数の大きさに応じて、
|
||
コンパイル済みのパターンが用いる記憶領域がより多く必要となります。
|
||
</para>
|
||
<para>
|
||
パターンが .* または .{0,} で始まっており、<link
|
||
linkend="reference.pcre.pattern.modifiers">PCRE_DOTALL</link>
|
||
オプション(Perl の /s に相当)が設定されている(つまり、
|
||
. が改行文字にもマッチする)場合、そのパターンは暗黙的に
|
||
固定パターンになります。.* もしくは .{0,} の後に続くパターンは、
|
||
対象文字列のすべての位置でマッチングが行われますが、パターン全体としては
|
||
対象文字列の始端以外でマッチングを再試行しても無駄だからです。PCRE は、
|
||
このようなパターンについては、その前に \A が記述されているものとして
|
||
扱います。こうした最適化を利用するために、
|
||
対象文字列が改行文字を含んでいなことが明らかな場合は、 .*
|
||
で始まるパターンに対し <link linkend="reference.pcre.pattern.modifiers">PCRE_DOTALL</link> を設定するか、
|
||
^ を用いて明示的に固定パターンとなるよう指定すると良いでしょう。
|
||
</para>
|
||
<para>
|
||
キャプチャ用サブパターンを繰り返した場合、キャプチャされる値は、
|
||
繰り返しの最後でマッチした部分文字列です。例えば、
|
||
|
||
<literallayout>
|
||
(tweedle[dume]{3}\s*)+
|
||
</literallayout>
|
||
|
||
を "tweedledum tweedledee" にマッチングさせた場合、キャプチャされる
|
||
部分文字列は、 "tweedledee" です。しかし、キャプチャ用サブパターンが
|
||
ネストしている場合、キャプチャされる値は、より前の繰り返しで
|
||
得られたものとなる可能性があります。例えば
|
||
|
||
<literallayout>
|
||
/(a|(b))+/
|
||
</literallayout>
|
||
|
||
を "aba" にマッチングさせると、キャプチャされた部分文字列の 2 番目のものは、
|
||
"b" になります。
|
||
</para>
|
||
</section>
|
||
|
||
<section xml:id="regexp.reference.back-references">
|
||
<title>後方参照</title>
|
||
<para>
|
||
文字クラス外で、バックスラッシュに続いて 1 以上の数値(複数桁可)
|
||
を記述したものは、パターン中のより前方(すなわち左)にある
|
||
キャプチャ用サブパターンに対する後方参照 (back reference) です。ただし、
|
||
その左方に、その数値以上の個数のキャプチャ用サブパターンの開きカッコが
|
||
ある必要があります。
|
||
</para>
|
||
<para>
|
||
なお、バックスラッシュの後に 10 未満の 10 進数が続く場合は
|
||
常に後方参照として解釈され、パターン全体で指定した個数以上の
|
||
キャプチャ用サブパターンが無いとエラーが発生します。言いかえると、
|
||
参照されるカッコは、10未満の番号に対しては、参照する側の左にある必要がないということです。
|
||
"前方にある後方参照 (forward back reference)" が意味をなすのは、
|
||
繰り返しが含まれていて、右側へのサブパターンがその前の反復に含まれている場合です。
|
||
バックスラッシュの後に数字が続く場合の処理の詳細については、
|
||
<link linkend="regexp.reference.escape">エスケープシーケンス</link>
|
||
のセクションを参照ください。
|
||
</para>
|
||
<para>
|
||
後方参照は、カレントの対象文字列においてキャプチャ用サブパターンが
|
||
実際にマッチした文字列にマッチします。サブパターンがパターンとして
|
||
マッチし得るものではありません。すなわち、パターン
|
||
|
||
<literallayout>
|
||
(sens|respons)e and \1ibility
|
||
</literallayout>
|
||
|
||
は、"sense and sensibility" および "response and responsibility"
|
||
にマッチしますが、 "sense and responsibility" にはマッチしません。また、
|
||
後方参照が記述されている位置で大小文字を区別するマッチングが有効ならば、
|
||
文字の大小文字の別も関係します。例えば、
|
||
|
||
<literallayout>
|
||
((?i)rah)\s+\1
|
||
</literallayout>
|
||
|
||
は、"rah rah" および "RAH RAH" にマッチしますが、
|
||
元のキャプチャ用サブパターンは大小文字を区別しないマッチングを
|
||
行っているにもかかわらず、"RAH rah" にはマッチしません
|
||
</para>
|
||
<para>
|
||
同じサブパターンに対して、複数回の後方参照を行うことができます。
|
||
また、使われなかったサブパターンに対する後方参照を行おうとすると、
|
||
マッチが失敗します。例えば、パターン
|
||
|
||
<literallayout>
|
||
(a|(bc))\2
|
||
</literallayout>
|
||
|
||
は、はじめに "bc" でなく "a" にマッチした場合は、マッチが失敗します。
|
||
最大 99 番までの後方参照を使用できるため、バックスラッシュの後に
|
||
数字が続くものはすべて後方参照番号の可能性があるものとして解釈されます。
|
||
後に数字が続く場合、後方参照を終了するためになんらかの区切り文字を
|
||
置く必要があります。<link
|
||
linkend="reference.pcre.pattern.modifiers">PCRE_EXTENDED</link>
|
||
オプションを設定している場合は空白文字を区切り文字として使えます。
|
||
その他の場合は空のコメントを使います。
|
||
</para>
|
||
<para>
|
||
後方参照を、それ自身が参照するサブパターンのカッコ内に記述した場合、
|
||
そのサブパターンが最初に使われた際にマッチが失敗します。ですので、
|
||
(a\1) は、何にもマッチしません。しかし、このような参照は、
|
||
複数回繰り返されるサブパターンの内部では有用です。例えば、パターン
|
||
|
||
<literallayout>
|
||
(a|b\1)+
|
||
</literallayout>
|
||
|
||
は、"a" が連続するものや "aba", "ababba" 等にマッチします。
|
||
サブパターンが繰り返される場合、後方参照は、直前の繰り返しで一致した
|
||
文字列にマッチします。こうしたパターンを動作させるためには、
|
||
繰り返しの1 回目に、後方参照を含むパターンとのマッチングが
|
||
行われないことが必要です。これには、上の例のように選択肢を使うか、
|
||
下限が 0 回の量指定子を使います。
|
||
</para>
|
||
<para>
|
||
エスケープシーケンス <literal>\g</literal>
|
||
を使ってサブパターンの絶対参照および相対参照を行うことができます。
|
||
このエスケープシーケンスの後には符号なしの数値あるいは負の数値を続けなければなりません。
|
||
数値は波括弧で囲むこともできます。<literal>\1</literal> と
|
||
<literal>\g1</literal> および <literal>\g{1}</literal> は、
|
||
すべて同じ意味になります。符号なし数値でこの方式を使えば、
|
||
バックスラッシュの後に数値を続ける方式がもつあいまいさを排除できます。
|
||
この方式を使えば後方参照と八進数値を明確に区別することができ、
|
||
さらに、後方参照のあとに数値リテラルが続く
|
||
<literal>\g{2}1</literal> のようなパターンも書きやすくなります。
|
||
</para>
|
||
<para>
|
||
<literal>\g</literal> シーケンスで負の数値を使うと、
|
||
それは相対参照を表します。たとえば
|
||
<literal>(foo)(bar)\g{-1}</literal> は
|
||
"foobarbar" にマッチし、<literal>(foo)(bar)\g{-2}</literal> は
|
||
"foobarfoo" にマッチします。
|
||
これは、長いパターンの中で特定のサブパターンを参照する場合に便利です。
|
||
それが何番目のサブパターンになるかをいちいち覚えておくかわりに、
|
||
相対指定することができるからです。
|
||
</para>
|
||
<para>
|
||
名前を指定したサブパターンへの後方参照を行うには
|
||
<literal>(?P=name)</literal> とします。
|
||
これ以外にも
|
||
<literal>\k<name></literal>,
|
||
<literal>\k'name'</literal>,
|
||
<literal>\k{name}</literal>,
|
||
<literal>\g{name}</literal>,
|
||
<literal>\g<name></literal>,
|
||
<literal>\g'name'</literal> の形も使えます。
|
||
</para>
|
||
</section>
|
||
|
||
<section xml:id="regexp.reference.assertions">
|
||
<title>言明</title>
|
||
<para>
|
||
言明 (assertion) とは、カレントのマッチング位置の直前・直後の文字に対する
|
||
テストであり、文字を消費 (consume)〔つまり文字自体にマッチ〕しません。
|
||
単純な言明コード \b, \B, \A, \Z, \z, ^ および $ については、
|
||
<link linkend="regexp.reference.escape">エスケープシーケンス</link> で説明しました。より複雑な言明は、サブパターンを用いて記述します
|
||
〔言明サブパターン (assertion subpattern) と呼ばれる〕。
|
||
言明サブパターンには、2 種類あります。対象文字列において
|
||
カレントの位置の<emphasis>先を読む</emphasis>ものと、<emphasis>後ろを読む</emphasis>ものです。
|
||
</para>
|
||
<para>
|
||
言明サブパターンは、カレントのマッチング位置を変更しないことを除き、
|
||
通常と同じようにマッチングが行われます。<emphasis>先読み</emphasis>言明 (lookahead assertion) は、
|
||
肯定の言明 (positive assertion) の場合 (?= で始まり、
|
||
否定の言明 (negative assertion) の場合 (?! で始まります。例えば、
|
||
|
||
<literallayout>
|
||
\w+(?=;)
|
||
</literallayout>
|
||
|
||
は、セミコロンが後に続く単語にマッチしますが、
|
||
マッチ対象それ自体にはセミコロンは含まれません。また、
|
||
|
||
<literallayout>
|
||
foo(?!bar)
|
||
</literallayout>
|
||
|
||
は、"bar" が後ろに続かない "foo" にマッチします。
|
||
なお、一見、良く似たパターンですが
|
||
|
||
<literallayout>
|
||
(?!foo)bar
|
||
</literallayout>
|
||
|
||
は、"foo" 以外のものの後にある "bar" を見つけるものではないことに
|
||
注意してください。これは、どこにある "bar" とでもマッチしてしまいます。
|
||
続く 3 文字が "bar" である場合、 (?!foo) は常に真となってしまうからです。
|
||
このような探索を実現するためには、戻り読み言明 (lookbehind assertion)
|
||
が必要です。
|
||
</para>
|
||
<para>
|
||
<emphasis>戻り読み</emphasis>言明は、肯定の言明の場合 (?<= で始まり、
|
||
否定の言明の場合 (?<! で始まります。例えば、
|
||
|
||
<literallayout>
|
||
(?<!foo)bar
|
||
</literallayout>
|
||
|
||
は、"foo" 以外の後にある "bar" の存在を見つけるものです。
|
||
戻り読み言明内のパターンは、それがマッチし得る文字列の長さが
|
||
固定でなければなりません〔繰り返しを指定できません〕。ただし、
|
||
選択肢を用いた場合、各選択肢は〔固定長でなければいけませんが〕
|
||
すべて同じ長さである必要はありません。つまり、
|
||
|
||
<literallayout>
|
||
(?<=bullock|donkey)
|
||
</literallayout>
|
||
|
||
とはできますが、
|
||
|
||
<literallayout>
|
||
(?<!dogs?|cats?)
|
||
</literallayout>
|
||
|
||
は、コンパイル時にエラーになります。
|
||
戻り読み言明の最上位においてのみ、異なる長さの文字列にマッチするような
|
||
選択肢が使用可能です。Perl 5.005 においては、すべての選択肢が
|
||
同じ長さの文字列にマッチする必要があります。つまり、この機能は
|
||
PCRE の拡張モジュールです。
|
||
|
||
<literallayout>
|
||
(?<=ab(c|de))
|
||
</literallayout>
|
||
|
||
という戻り読み言明は、最上位にひとつの選択肢しかなく、
|
||
その選択肢は異なる長さの文字列にマッチしうるので、不正です。
|
||
しかし、
|
||
|
||
<literallayout>
|
||
(?<=abc|abde)
|
||
</literallayout>
|
||
|
||
のように、最上位において選択肢を 2 つ用いるように
|
||
書き換えると使用可能です。
|
||
</para>
|
||
<para>
|
||
後方言明の実装においては、選択肢ことに一時的に固定の幅だけ
|
||
カレントの位置を後退させ、マッチを試みます。カレントの位置の前に
|
||
十分な文字がない場合は、マッチは失敗とみなされます。
|
||
再試行無しのサブパターンと組み合わせた戻り読み言明は、
|
||
文字列の終端でのマッチングに特に有用です。
|
||
再試行無しのサブパターンについてのセクションの最後にて例を示します。
|
||
</para>
|
||
<para>
|
||
(任意の種類の)複数の言明を連続して指定することも可能です。例えば、
|
||
|
||
<literallayout>
|
||
(?<=\d{3})(?<!999)foo
|
||
</literallayout>
|
||
|
||
は、"999" でない 3 桁の数字の後にある "foo" にマッチします。
|
||
それぞれの言明は、対象文字列の同じ場所に独立して適用されることに
|
||
注意して下さい。まず、前の 3 文字がすべて数字であることがチェックされ、
|
||
続いて、同じ 3 文字が "999" でないことが確認されます。このパターンは、
|
||
"foo" の前に 6 個の文字があり、その前半が数字で後半の 3 文字が "999"
|
||
でないというパターンにマッチするものではありません。例えば、"123abcfoo"
|
||
にはマッチしません。これを行うパターンは次のようになります。
|
||
|
||
<literallayout>
|
||
(?<=\d{3}...)(?<!999)foo
|
||
</literallayout>
|
||
</para>
|
||
<para>
|
||
この時、最初の言明は、先行する 6 つの文字を探し、
|
||
最初の 3 文字が数字であることを確認します。続いて、2 番目の言明は、
|
||
先行する 3 文字が "999" でないことを確認します。
|
||
</para>
|
||
<para>
|
||
言明は、自由に組み合わせてネスト可能です。例えば、
|
||
|
||
<literallayout>
|
||
(?<=(?<!foo)bar)baz
|
||
</literallayout>
|
||
|
||
は、"foo" 以外の後にある "bar" の後に有る "bar" があればマッチします。
|
||
一方、
|
||
|
||
<literallayout>
|
||
(?<=\d{3}...(?<!999))foo
|
||
</literallayout>
|
||
|
||
は、999 でない 3 桁の数字とさらに 3 文字の後に続く "foo"
|
||
にマッチするパターンです。
|
||
</para>
|
||
<para>
|
||
言明サブパターンは、キャプチャ用サブパターンではありません
|
||
〔値のキャプチャは行われません〕。繰り返しもできません。
|
||
同じことを複数回言明しても意味がないからです。
|
||
キャプチャ用サブパターンが言明の内部に含まれている場合、
|
||
言明の種類に関係なく、キャプチャ用サブパターンの番号付けにあたって
|
||
カウントされます。しかし、文字列のキャプチャは、肯定の言明に対してのみ
|
||
行われます。否定の言明の中で行っても無意味だからです。
|
||
</para>
|
||
<para>
|
||
カッコ付サブパターンによる言明は、最大 200 まで用いることができます。
|
||
</para>
|
||
</section>
|
||
|
||
<section xml:id="regexp.reference.onlyonce">
|
||
<title>再試行無しのサブパターン</title>
|
||
<para>
|
||
繰り返し回数の下限もしくは上限の指定をした場合、
|
||
〔繰り返しを指定した要素の〕続きがマッチに失敗すると、
|
||
繰り返し指定した要素が再評価され、繰り返し回数を変えた上で
|
||
残りのパターンがマッチするかどうか試されます。
|
||
マッチングを続けても無駄なことが明らかな場合、マッチングの性質を変え、
|
||
より速くマッチに失敗させるために、こうした動作を停止させることが
|
||
有用な場合があります。
|
||
</para>
|
||
<para>
|
||
例えば、パターン \d+foo を
|
||
"123456bar"
|
||
という対象文字列に適用した場合を考えてみましょう。
|
||
</para>
|
||
<para>
|
||
\d+ が 6 桁の数字すべてにマッチしますが、その後 "foo"
|
||
とのマッチが失敗します。通常のマッチング処理の動作だと、5桁の数字のみが
|
||
\d+ にマッチするとして再試行され、次いで 4 桁等々と続けられ、
|
||
最後には完全にマッチが失敗します。再試行無しのサブパターン
|
||
(once-only subpattern) を用いると、パターンの一部が一度マッチしたら、
|
||
その後再評価されないよう指定することができます。つまり、最初に "foo"
|
||
とのマッチに失敗した時点で、ただちにマッチングを取り止めることが
|
||
可能となります。表記には、
|
||
|
||
<literallayout>
|
||
(?>\d+)bar
|
||
</literallayout>
|
||
|
||
のように、(?> で始まる特別なカッコを用います。
|
||
</para>
|
||
<para>
|
||
この種類のカッコは、一度マッチしたパターンの部分に鍵をかけ (lock up)
|
||
ます。そのパターンへの再マッチは失敗し、バックトラック (backtrack)
|
||
が起こらないようにします。それより前の要素に対するバックトラックは、
|
||
通常と同様に動作します。
|
||
</para>
|
||
<para>
|
||
別の説明をすると、このタイプのサブパターンは、同一のスタンドアローンの
|
||
パターンが対象文字列のカレントの位置に固定されたかのように、
|
||
文字列とマッチします。
|
||
</para>
|
||
<para>
|
||
再試行無しのサブパターンは、キャプチャ用サブパターンではありません
|
||
〔つまり、値のキャプチャは行われません〕。上の簡単な例では、
|
||
できるだけ多くのものを呑み込むよう繰り返しが最大化されました。つまり、
|
||
+ や +? は残りのパターンがマッチするよう数字の桁数が調整されるのに
|
||
対して、 (?>+) は数字の並び全体に対するマッチングだけしか行われません。
|
||
</para>
|
||
<para>
|
||
この構文には、どんな複雑なものでも、任意のサブパターンを含むことができ、
|
||
ネストも可能です。
|
||
</para>
|
||
<para>
|
||
再試行無しのサブパターンと戻り読み言明とを組み合わせると、
|
||
対象文字列の終端における効率的なマッチングを行うことができます。
|
||
|
||
<literallayout>
|
||
abcd$
|
||
</literallayout>
|
||
|
||
というパターンを見てましょう。
|
||
|
||
マッチが成功しない長い文字列に適用した場合を考えます。
|
||
マッチングは左から右に行われるため、PCRE は対象文字列のすべての "a" を探し、
|
||
後に続く文字が残りのパターンにマッチするかどうか調べられます。
|
||
|
||
パターンを
|
||
|
||
<literallayout>
|
||
^.*abcd$
|
||
</literallayout>
|
||
|
||
のように少し変更してみます。
|
||
|
||
この場合、最初の .* は、まず文字列全体にマッチします。
|
||
("a" がその後に続かないので)マッチが失敗すると、最後の 1 文字を除く
|
||
文字列にマッチするようバックトラックが行なわれ、続いて最後の 2 文字を
|
||
除く文字列に、という風に動作します。 "a" の検索は、やはり文字列全体に
|
||
対して、右から左に、行われるため効率は良くありません。
|
||
|
||
しかし、パターンを
|
||
|
||
<literallayout>
|
||
^(?>.*)(?<=abcd)
|
||
</literallayout>
|
||
|
||
のようにしてみましょう。
|
||
|
||
要素 .* に対してバックトラックは行われず、文字列全体にのみマッチします。
|
||
続く戻り読み言明は、最後の 4 文字に対するテストを 1 回だけ行います。
|
||
テストが失敗すると、マッチはただちに失敗します。長い文字列に対しては、
|
||
この方法を用いると実行時間にかなりの差が生じます。
|
||
</para>
|
||
<para>
|
||
パターン中にサブパターンがあって、その中に繰り返し数に
|
||
上限の無い要素があり、そのサブパターン自身も何回でも繰り返しが
|
||
可能な場合、マッチの失敗に非常に長い時間がかかってしまう事があります。
|
||
それを避ける唯一の方法は再試行無しのサブパターンを使うことです。
|
||
パターン
|
||
|
||
<literallayout>
|
||
(\D+|<\d+>)*[!?]
|
||
</literallayout>
|
||
|
||
は、非数字もしくは <> で括られた数字に ! または ? が続く
|
||
任意の長さの部分文字列にマッチします。マッチが成功するような
|
||
対象文字列に対しては、速く動作します。
|
||
しかし、これを
|
||
|
||
<literallayout>
|
||
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||
</literallayout>
|
||
|
||
に適用すると、マッチが失敗するまでに長い時間がかかります。これは、
|
||
この対象文字列を分割するやり方が数多くあり、それらすべてに対し
|
||
マッチを試みられる事になるためです。
|
||
(この例で、終端に単一の文字ではなく [!?] を使っているのは、
|
||
PCRE と Perl の双方とも、〔終端に〕単一の文字が使われると、
|
||
より速く失敗と判定できるように最適化が行われる
|
||
〔ので、それを避ける〕ためです。マッチに必要な最後の一文字が記憶され、
|
||
文字列にその文字が無い場合、早期に失敗と判定されます。)
|
||
このパターンを
|
||
|
||
<literallayout>
|
||
((?>\D+)|<\d+>)*[!?]
|
||
</literallayout>
|
||
|
||
のように変更した場合、非数字の部分が分割されることがなくなるので、
|
||
より速くマッチが失敗するようになります。
|
||
</para>
|
||
</section>
|
||
|
||
<section xml:id="regexp.reference.conditional">
|
||
<title>条件付きサブパターン</title>
|
||
<para>
|
||
サブパターンを条件付きでマッチング処理させることが可能です。
|
||
言明の結果や直前のキャプチャ用サブパターンがマッチしたかどうかにより、
|
||
サブパターン中の 2 つの選択肢を選択させます。条件付きサブパターン
|
||
(conditional subpattern) には、 2 つの形式があります。
|
||
</para>
|
||
|
||
<informalexample>
|
||
<programlisting>
|
||
<![CDATA[
|
||
(?(条件)真パターン)
|
||
(?(条件)真パターン|偽パターン)
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
<para>
|
||
条件が満たされた場合、真パターンが使われます。そうでない場合は、
|
||
(もしあれば)偽パターンが使われます。サブパターン内に 3 つ以上の
|
||
選択肢があると、コンパイル時にエラーになります。
|
||
</para>
|
||
<para>
|
||
条件には 2 種類あります。条件のカッコ内が数値の場合、
|
||
その番号のキャプチャ用サブパターンがマッチしている場合に条件が
|
||
真となります。カッコ内の数値は 1 以上でないといけません。
|
||
次のパターンを見てみましょう。可読性を高めるために意味のない空白文字が
|
||
挿入され(<link linkend="reference.pcre.pattern.modifiers">PCRE_EXTENDED</link>
|
||
オプションが指定されていると仮定します)、
|
||
説明を簡単にするため 3 つの部分に分割されています。
|
||
</para>
|
||
<informalexample>
|
||
<programlisting>
|
||
<![CDATA[
|
||
( \( )? [^()]+ (?(1) \) )
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
<para>
|
||
最初の部分は、オプションで、開きカッコにマッチします。
|
||
開きカッコが有る場合、1 番のキャプチャ文字列にセットされます。
|
||
第 2 の部分は、カッコでない一つ以上の文字にマッチします。第 3 の部分は、
|
||
最初のカッコがマッチしたかどうかをテストする条件付きサブパターンです。
|
||
カッコにマッチしている場合、つまり、対象文字列が開きカッコで
|
||
始まっている場合、条件は真となり、真パターンが実行され、閉じカッコが
|
||
必要となります。そうでない場合、偽パターンが存在しないため、
|
||
サブパターンは何にもマッチしません。言いかえると、このパターンは、
|
||
カッコなしの並びにマッチするものですが、オプションで
|
||
カッコで囲まれた並びにもマッチします。
|
||
</para>
|
||
<para>
|
||
<literal>(R)</literal> という文字列を条件として指定すると、パターン全体もしくは
|
||
サブパターンへの再帰的呼び出しがなされた場合に、その条件が満たされることになります。
|
||
「トップレベル」においては、この条件は偽となります。
|
||
</para>
|
||
<para>
|
||
数値の他にも、条件として言明が使用できます。先読み言明と
|
||
戻り読み言明のいずれも使え、肯定の言明も否定の言明も使用できます。
|
||
次のパターンを見てみましょう。このパターンにも意味のない空白文字が
|
||
挿入されており、2 行目に 2 つの選択肢が 書かれています。
|
||
</para>
|
||
|
||
<informalexample>
|
||
<programlisting>
|
||
<![CDATA[
|
||
(?(?=[^a-z]*[a-z])
|
||
\d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} )
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
<para>
|
||
条件は、肯定の先読み言明であり、英字以外の文字の並びの後に英字が
|
||
続くものにマッチします。言いかえると、対象文字列に少なくとも英字が
|
||
一つあるかどうかが調べられます。英字がみつかると、最初の選択肢に対して
|
||
検索対象とのマッチングが行われます。みつからない場合は、2番目の選択肢に
|
||
対してマッチングが行われます。このパターンは、2つの形式 dd-aaa-dd
|
||
または dd-dd-dd のどちらかの文字列にマッチします。ここで、aaa は英字、
|
||
dd は数字です。
|
||
</para>
|
||
</section>
|
||
|
||
<section xml:id="regexp.reference.comments">
|
||
<title>コメント</title>
|
||
<para>
|
||
コメントは、(?# という並びにより始まり、次の閉じカッコで終わります。
|
||
カッコのネストはできません。コメント内の文字は、パターンマッチには
|
||
全く関係しません。
|
||
</para>
|
||
<para>
|
||
<link linkend="reference.pcre.pattern.modifiers">PCRE_EXTENDED</link>
|
||
オプションが設定されている場合は、パターン中の文字クラス外にある
|
||
エスケープされていない # 文字からもコメントが始まり、
|
||
次の改行文字で終わります。
|
||
</para>
|
||
<para>
|
||
<example>
|
||
<title>パターンの中でのコメントの使い方</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
$subject = 'test';
|
||
|
||
/* PCRE_EXTENDED を有効にせずにコメントを追加するには, (?# を使います */
|
||
$match = preg_match('/te(?# this is a comment)st/', $subject);
|
||
var_dump($match);
|
||
|
||
/* 空白文字と # は、PCRE_EXTENDED が無効の場合、パターンの一部として扱われます */
|
||
$match = preg_match('/te #~~~~
|
||
st/', $subject);
|
||
var_dump($match);
|
||
|
||
/* PCRE_EXTENDED が有効な場合、全ての空白文字のデータや、エスケープされていない # の後に続く全てが無視されます */
|
||
$match = preg_match('/te #~~~~
|
||
st/x', $subject);
|
||
var_dump($match);
|
||
]]>
|
||
</programlisting>
|
||
&example.outputs;
|
||
<screen>
|
||
<![CDATA[
|
||
int(1)
|
||
int(0)
|
||
int(1)
|
||
]]>
|
||
</screen>
|
||
</example>
|
||
</para>
|
||
</section>
|
||
|
||
<section xml:id="regexp.reference.recursive">
|
||
<title>再帰的パターン</title>
|
||
<para>
|
||
どうすればカッコに括られた文字列とマッチできるか、という問題を
|
||
考えて見ましょう。このとき、カッコは何回でもネストできるとします。
|
||
再帰が使えないとすると、パターンを用いて、せいぜい、ある一定の深さの
|
||
ネストまでしかマッチできないでしょう。任意の深さのネストを
|
||
処理することは不可能です。Perl 5.6 では、正規表現において再帰を行う
|
||
実験的な機能が導入されています。
|
||
PCRE では、再帰という特殊なケースに対して専用のシーケンス (?R)
|
||
が導入されました。上記のカッコ問題を解決する PCRE のコードは
|
||
以下のようになります(<link
|
||
linkend="reference.pcre.pattern.modifiers">PCRE_EXTENDED</link>
|
||
オプションが設定され空白文字が無視されると仮定)。
|
||
|
||
<literallayout>
|
||
\( ( (?>[^()]+) | (?R) )* \)
|
||
</literallayout>
|
||
</para>
|
||
<para>
|
||
まず、このパターンは開きカッコにマッチします。続いて、
|
||
カッコ以外の文字が並んでいるか、または、再帰的にパターン自体に
|
||
マッチする(すなわち正しくカッコで括られている)かする部分文字列に
|
||
何回でもマッチします。最後に閉じカッコにマッチします。
|
||
</para>
|
||
<para>
|
||
このパターン例には、ネストした無制限の繰り返しが含まれているため、
|
||
マッチが成功し得ない文字列に対してこのパターンが適用される場合も考えて、
|
||
カッコ以外の文字列にマッチングさせる部分に再試行無しのサブパターンを
|
||
使うことが重要です。例えば、このパターンを
|
||
|
||
<literallayout>
|
||
(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa()
|
||
</literallayout>
|
||
|
||
という文字列に適用すると、「マッチしない」という判定が速やかに
|
||
行われます。しかし、再試行無しのサブパターンを使わないと、
|
||
対象文字列を分割し得る + と * の繰り返し数の種類が非常に多く、
|
||
そのすべてが確認された後にマッチの失敗が報告されるため、
|
||
マッチングに非常に時間がかかります。
|
||
</para>
|
||
<para>
|
||
キャプチャ用サブパターンにセットされる値は、そのサブパターンに
|
||
値がセットされ得る最も外側で最も後の再帰レベルからのものになります。
|
||
上記のパターンを
|
||
|
||
<literallayout>
|
||
(ab(cd)ef)
|
||
</literallayout>
|
||
|
||
にマッチングさせると、キャプチャされる値は "ef" であり、
|
||
最上位レベルの最後の値です
|
||
|
||
<literallayout>
|
||
\( ( ( (?>[^()]+) | (?R) )* ) \)
|
||
</literallayout>
|
||
|
||
次のようにカッコを追加すると、キャプチャされる文字列は、"ab(cd)ef"
|
||
となり、最上位レベルのカッコの中身となります。一つのパターン中に
|
||
15 以上のキャプチャ用サブパターンを用いると、PCRE は
|
||
再帰を行っている間のデータ保存用に追加の記憶領域を確保する必要が
|
||
あります。記憶領域が確保できない場合、メモリ不足エラーを再帰の内側から
|
||
出力する手段がないため、最初の 15 個のキャプチャ用サブパターンに
|
||
ついてのみデータが保存されます。
|
||
</para>
|
||
|
||
<para>
|
||
<literal>(?1)</literal>, <literal>(?2)</literal> といった記法が
|
||
再帰的サブパターンとして使用可能です。
|
||
<literal>(?P>name)</literal> あるいは <literal>(?&name)</literal>
|
||
といった名前付きのサブパターンも使用可能です。
|
||
</para>
|
||
<para>
|
||
この再帰的サブパターンの記法は(数字によるものも名前によるものの双方とも)
|
||
参照するカッコの外で使用でき、プログラム言語のサブルーチンの様に処理されます。
|
||
前に示した例で、パターン <literal>(sens|respons)e and \1ibility</literal>
|
||
は "sense and sensibility" および "response and responsibility" にはマッチしますが
|
||
"sense and responsibility" にはマッチしませんでした。
|
||
一方、パターン <literal>(sens|respons)e and (?1)ibility</literal> は、
|
||
上記 2 つに加え "sense and responsibility" にもマッチします。
|
||
ただし、参照先のサブパターンの後に記述する必要があります。
|
||
</para>
|
||
|
||
<para>
|
||
対象文字列の最大の長さは、integer 型の最大の値となります。
|
||
しかし、PCRE は再帰を使用してサブパターンの処理や繰り返し処理を行います。
|
||
つまり、そのパターンで処理する対象文字列の長さによって、
|
||
使用可能なスタック空間の大きさが制限されるということです。
|
||
</para>
|
||
|
||
</section>
|
||
|
||
<section xml:id="regexp.reference.performance">
|
||
<title>パフォーマンス</title>
|
||
<para>
|
||
パターンに記述可能な要素のうち、幾つかの要素は、他の要素よりも
|
||
効率的に処理されます。 (a|e|i|o|u) のような選択肢の集合よりも
|
||
[aeiou] のような文字クラスの方が効率的です。一般に、構文が
|
||
最も単純なものが、たいてい最も効率が良くなります。Jeffrey Friedl
|
||
の本には、正規表現の性能を向上させる最適化について
|
||
様々な検討が行われています。
|
||
</para>
|
||
<para>
|
||
パターンが .* で始まり、<link
|
||
linkend="reference.pcre.pattern.modifiers">PCRE_DOTALL</link>
|
||
オプションを設定した場合、対象文字列の始端でしかマッチできないため、
|
||
PCRE は、暗黙のうちにそのパターンを固定パターンとみなします。しかし、
|
||
PCRE_DOTALL を設定しない場合、メタ文字 . が改行にマッチせず、
|
||
対象文字列が改行を含む場合、パターンは文字列の始端からではなく各改行の
|
||
直後の文字からマッチする可能性があるため、PCRE は
|
||
この最適化を行うことができません。
|
||
|
||
例えば、パターン
|
||
|
||
<literallayout>
|
||
(.*) second
|
||
</literallayout>
|
||
|
||
を、対象文字列 "first\nand second"(ここで、\n は改行文字を意味します)に
|
||
マッチングさせます。 1 番目のキャプチャ文字列は、"and" になります。
|
||
このような動作をするには、 PCRE は対象文字列の各改行文字の後から
|
||
マッチングを繰り返し行う必要があります。
|
||
</para>
|
||
<para>
|
||
このようなパターンを、改行を含まない対象文字列に適用する場合は、
|
||
<link linkend="reference.pcre.pattern.modifiers">PCRE_DOTALL</link>
|
||
を設定するか、固定パターンであることを明示的に示すためにパターンを
|
||
^.* で開始すると最高の性能が得られます。そうすることで、PCRE
|
||
が対象文字列の改行を探し、そこからマッチングが再び始められることを
|
||
防止します。
|
||
</para>
|
||
<para>
|
||
制限のない繰り返しをネストするようなパターンについては注意が必要です。
|
||
そのようなパターンが、マッチが成功し得ない文字列に適用された場合には、
|
||
実行に長い時間を要します。
|
||
|
||
<literallayout>
|
||
(a+)*
|
||
</literallayout>
|
||
|
||
というパターンを考えてみましょう。
|
||
</para>
|
||
<para>
|
||
このパターンが "aaaa" にマッチし得る方法は 33 通りもあります(つまり、
|
||
* による繰り返しは 0, 1, 2, 3 もしくは 4 回の繰り返しにマッチし、
|
||
0 回以外のそれぞれの場合について、 + による繰り返しは様々な回数分
|
||
マッチします)〔訳注:a 1文字の 4 回繰り返しとか、 a 1文字とa 3文字の
|
||
組合せとかを意味する〕。この数は、文字列が長くなるにつれて急激に
|
||
増大します。このパターンの後ろに、マッチが失敗するような別のパターンが
|
||
続いていて、パターン全体としてマッチが失敗してしまう場合、PCREは、基本的に
|
||
取り得るすべての選択肢を調べるため、非常に長い時間がかかります。
|
||
</para>
|
||
<para>
|
||
<literallayout>
|
||
(a+)*b
|
||
</literallayout>
|
||
|
||
のように単一の文字リテラルが最後にある場合には最適化が行われます。
|
||
|
||
標準のマッチング手順に着手する前に、PCRE は対象文字列の後方に "b"
|
||
があるかどうかを調べます。無い場合には、直ちにマッチは失敗します。
|
||
文字リテラルが最後にない場合には、この最適化は行われません。
|
||
|
||
<literallayout>
|
||
(a+)*\d
|
||
</literallayout>
|
||
|
||
というパターンと上に挙げたパターンの動作を比較してみましょう。
|
||
|
||
"a" 文字だけが連続する行に適用した場合、前者のパターンでは、
|
||
ほぼ瞬間的に失敗と判定されます。一方、後者のパターンでは、
|
||
文字列の長さがおよそ 20 文字を超えると、かなりの時間がかかります。
|
||
</para>
|
||
</section>
|
||
</chapter>
|
||
|
||
<!-- Keep this comment at the end of the file
|
||
Local variables:
|
||
mode: sgml
|
||
sgml-omittag:t
|
||
sgml-shorttag:t
|
||
sgml-minimize-attributes:nil
|
||
sgml-always-quote-attributes:t
|
||
sgml-indent-step:1
|
||
sgml-indent-data:t
|
||
indent-tabs-mode:nil
|
||
sgml-parent-document:nil
|
||
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
|
||
sgml-exposed-tags:nil
|
||
sgml-local-catalogs:nil
|
||
sgml-local-ecat-files:nil
|
||
End:
|
||
vim600: syn=xml fen fdm=syntax fdl=2 si
|
||
vim: et tw=78 syn=sgml
|
||
vi: ts=1 sw=1
|
||
-->
|