Perl の正規表現構文

概要

Perl の正規表現構文は、プログラミング言語 Perl で使われているものに基づいている。Perl の正規表現は Boost.Regex の既定の動作であり、basic_regex のコンストラクタにフラグ perl を渡すことでも利用できる。例えば以下のとおり。

// e1 は大文字小文字を区別する Perl の正規表現:
// Perl は既定のオプションであり、明示的に構文を指定する必要はない:
boost::regex e1(my_expression);
// e2 は大文字小文字を区別しない Perl の正規表現:
boost::regex e2(my_expression, boost::regex::perl|boost::regex::icase);

Perl の正規表現構文

Perl の正規表現では、以下の特別なものを除くあらゆる文字が文字そのものにマッチする。

.[{()\*+?|^$

他の文字は特定の場合のみ特別扱いである。例えば ] は開き [ の後のみ特別扱いとなる。

ワイルドカード

文字集合外部の . 1 文字は、以下以外のあらゆる文字1文字にマッチする。

  • NULL 文字(マッチアルゴリズムにフラグ match_not_dot_null を渡した場合)。

  • 改行文字(マッチアルゴリズムにフラグ match_not_dot_newline を渡した場合)。

アンカー

^ は行頭にマッチする。

$ は行末にマッチする。

マーク済み部分式

開始が ( で終了が ) の節は部分式として機能する。マッチした部分式はすべてマッチアルゴリズムにより個別のフィールドに分けられる。マーク済み部分式は繰り返しと後方参照により参照が可能である。

マークなしのグループ化

マーク済み部分式は正規表現を字句的なグループに分けるのに役立つが、結果的に余分なフィールドを生成するという副作用がある。マーク済み部分式を生成することなく正規表現を字句的なグループに分ける別の手段として、(?:) を使う方法がある。例えば (?:ab)+ab の繰り返しを表し、別個の部分式を生成しない。

繰り返し

あらゆるアトム(文字、部分式、文字クラス)は *+? および {} 演算子による繰り返しが可能である。

* 演算子は直前のアトムの 0 回以上の繰り返しにマッチする。例えば正規表現 a*b は以下のいずれにもマッチする。

b
ab
aaaaaaaab

+ 演算子は直前のアトムの 1 回以上の繰り返しにマッチする。例えば正規表現 a+b は以下のいずれにもマッチする。

ab
aaaaaaaab

しかし次にはマッチしない。

b

? 演算子は直前のアトムの 0 回あるいは 1 回の出現にマッチする。例えば正規表現 ca?b は以下のいずれにもマッチする。

cb
cab

しかし次にはマッチしない。

caab

アトムの繰り返しは回数境界指定の繰り返しによっても可能である。

a{n}a のちょうど n 回の繰り返しにマッチする。

a{n,}a の n 回以上の繰り返しにマッチする。

a{n,m}a の n 回以上 m 回以下の繰り返しにマッチする。

例えば

^a{2,3}$

は、次のいずれにもマッチするが、

aa
aaa

次のいずれにもマッチしない。

a
aaaa

文字 { および } は、繰り返し以外の場面では通常のリテラルとして扱うことに注意していただきたい。これは Perl 5.x と同じ振る舞いである。例えば式 ab{1ab1} および a{b}c の波括弧はリテラルとして扱い、エラーは発生しない

直前の構造が繰り返し不能な場合に繰り返し演算子を使うとエラーになる。例えば次は

a(*)

* 演算子を適用可能なものがないためエラーとなる。

貪欲でない繰り返し

通常の繰り返し演算子は「貪欲」である。貪欲とは、可能な限り長い入力にマッチするという意味である。マッチを生成する中で最も短い入力に一致する貪欲でないバージョンがある。

*? は直前のアトムの 0 回以上の繰り返しにマッチする最短バージョンである。

+? は直前のアトムの 1 回以上の繰り返しにマッチする最短バージョンである。

?? は直前のアトムの 0 回か 1 回の出現にマッチする最短バージョンである。

{n,}? は直前のアトムの n 回以上の繰り返しにマッチする最短バージョンである。

{n,m}? は直前のアトムの n 回以上 m 回以下の繰り返しにマッチする最短バージョンである。

強欲な繰り返し

既定では、繰り返しパターンがマッチに失敗すると正規表現エンジンはマッチが見つかるまでバックトラッキングを行う。しかしながらこの動作が不都合な場合があるため、「強欲な」繰り返しというものがある。可能な限り長い文字列にマッチするが、式の残りの部分がマッチに失敗してもバックトラックを行わない。

*+ は直前のアトムの 0 回以上の繰り返しにマッチし、バックトラックを行わない。

++ は直前のアトムの 1 回以上の繰り返しにマッチし、バックトラックを行わない。

?+ は直前のアトムの 0 回か 1 回の出現にマッチし、バックトラックを行わない。

{n,}+ は直前のアトムの n 回以上の繰り返しにマッチし、バックトラックを行わない。

{n,m}+ は直前のアトムの n 回以上 m 回以下の繰り返しにマッチし、バックトラックを行わない。

後方参照

エスケープ文字の直後に数字 n があると、部分式 n にマッチしたものと同じ文字列にマッチする。n は 0 から 9 の範囲である。例えば次の正規表現は、

^(a*)[^a]*\1$

次の文字列にマッチする。

aaabbaaa

しかし、次の文字列にはマッチしない。

aaabba

\g エスケープを使用しても同じ効果が得られる。例えば、

エスケープ

意味

\g1

1 番目の部分式にマッチ。

\g{1}

1 番目の部分式にマッチ。この形式を使うと \g{1}2 のような式や、\g{1234} といった添字が 9 より大きい式を安全に解析できる。

\g-1

最後の部分式にマッチ。

\g{-2}

最後から 2 番目の部分式にマッチ。

\g{one}

“one” という名前の部分式にマッチ。

後方参照は、その時点で見つかっていない部分式への前方参照としても機能することに注意していただきたい。これは繰り返し内のみの話であり、例えば (\2two|(one))oneonetwo にマッチする。

最後に、\k エスケープで名前付き部分式を参照できる。例えば \k<two> は “two” という名前の部分式にマッチする。

選択

| 演算子は引数のいずれかにマッチする。よって、例えば abc|defabcdef のいずれかにマッチする。

括弧を使用すると選択をグループ化できる。例えば ab(d|ef)abdabef のいずれかにマッチする。

空の選択というのは許されないが、本当に必要な場合はプレースホルダーとして (?:) を使用する。例えば、

  • |abc は有効な式ではない。

  • しかし、(?:)|abc は有効な式であり、実現しようとしていることは同じである。

  • (?:abc)?? も全く同じ意味である。

文字集合

文字集合は [ で始まり ] で終わる括弧式であり、文字の集合を定義する。集合に含まれるいずれかの 1 文字にマッチする。

文字集合に含められる要素は以下の組み合わせである。

単一の文字

例えば [abc]abc のいずれか 1 文字にマッチする。

文字範囲

例えば [a-c] は ‘a’ から ‘c’ までの範囲の 1 文字にマッチする。Perl の正規表現の既定では、文字 xy から z の範囲であるとは、文字のコードポイントが範囲の端点を含んだコードポイント内にある場合をいう。ただし、正規表現の構築時に collate フラグ設定するとこの範囲はロカール依存となる。

否定

括弧式が文字 ^ で始まっている場合は、正規表現に含まれる文字の補集合となる。例えば [^a-c] は範囲 a-c を除くあらゆる文字にマッチする。

文字クラス

[[:name:]] のような形式の正規表現は名前付き文字クラス「name」にマッチする。例えば [[:lower:]] はあらゆる小文字にマッチする。文字クラス名を見よ。

照合要素

[[.col.]] のような形式の式は照合要素 col にマッチする。照合要素とは、単一の照合単位として扱われる文字か文字シーケンスである。照合要素は範囲の端点としても使用できる。例えば [[.ae.]-c] は文字シーケンス “ae” のみならず、範囲 “ae”-c のいずれか 1 文字にもマッチする。 後者において “ae” は現在のロカールにおける単一の照合要素として扱われる。

この拡張として、照合要素をシンボル名で指定する方法もある。例えば、

[[.NUL.]]

は文字 \0 にマッチする。

等価クラス

[[=col=]] のような形式の正規表現は、第 1 位のソートキーが照合要素 col と同じ文字および照合要素にマッチする。照合要素名 colシンボル名でもよい。第 1 位のソートキーでは大文字小文字の違い、アクセント記号の有無、ロカール固有のテーラリング 1 は無視される。よって [[=a=]] は a 、À 、Á 、Â 、Ã 、Ä 、Å 、A 、à 、á 、â 、ã 、ä および å のいずれにもマッチする。残念ながらこの機能の実装はプラットフォームの照合と地域化のサポートに依存し、すべてのプラットフォームで移植性の高い動作は期待できず、単一のプラットフォームにおいてもすべてのロカールで動作するとは限らない。

エスケープ付き文字

1 文字にマッチするエスケープシーケンスおよび文字クラスが、文字クラスの定義で使用可能である。例えば [\[\]][] のいずれかにマッチする。また [\W\d] は「数字」か、「単語」でない 1 文字にマッチする。

結合

以上の要素はすべて 1 つの文字集合宣言内で結合可能である。例: [[:digit:]a-c[.NUL.]]

エスケープ

直前にエスケープの付いた特殊文字は、すべてその文字自身にマッチする。

以下のエスケープシーケンスは、すべて 1 文字の別名である。

エスケープ

文字

\a

\a

\e

0x1B

\f

\f

\n

\n

\r

\r

\t

\t

\v

\v

\b

\b(文字クラス宣言内のみ)

\cX

ASCII エスケープシーケンス。コードポイントが X % 32の文字

\xdd

16 進エスケープシーケンス。コードポイントが 0xdd の文字にマッチする。

\x{dddd}

16 進エスケープシーケンス。コードポイントが 0xdddd の文字にマッチする。

\0ddd

8 進エスケープシーケンス。コードポイントが 0ddd の文字にマッチする。

\N{name}

シンボル名 name の文字にマッチする。例えば \N{newline} は文字 \n にマッチする。

「単一文字」文字クラス

x が文字クラス名である場合、エスケープ文字 x はその文字クラスに属するあらゆる文字にマッチし、エスケープ文字 X はその文字クラスに属さないあらゆる文字にマッチする。

既定でサポートされているものは以下のとおりである。

エスケープシーケンス

等価な文字クラス

\d

[[:digit:]]

\l

[[:lower:]]

\s

[[:space:]]

\u

[[:upper:]]

\w

[[:word:]]

\h

水平空白

\v

垂直空白

\D

[^[:digit:]]

\L

[^[:lower:]]

\S

[^[:space:]]

\U

[^[:upper:]]

\W

[^[:word:]]

\H

水平空白以外

\V

垂直空白以外

文字プロパティ

次の表の文字プロパティ名はすべて文字クラスで使用する名前と等価である。

形式

説明

等価な文字集合の形式

\pX

プロパティ X をもつあらゆる文字にマッチする。

[[:X:]]

\p{Name}

プロパティ Name をもつあらゆる文字にマッチする。

[[:Name:]]

\PX

プロパティ X をもたないあらゆる文字にマッチする。

[^[:X:]]

\P{Name}

プロパティ Name をもたないあらゆる文字にマッチする。

[^[:Name:]]

例えば \pd\p{digit} と同様、あらゆる「数字」(“digit”)にマッチする。

単語境界

次のエスケープシーケンスは単語の境界にマッチする。

\< は単語の先頭にマッチする。

\> は単語の終端にマッチする。

\b は単語境界(単語の先頭か終端)にマッチする。

\B は単語境界以外にマッチする。

バッファ境界

以下はバッファ境界にのみマッチする。この場合の「バッファ」とは、マッチ対象の入力テキスト全体である(^ および $ はテキスト中の改行にもマッチすることに注意していただきたい)。

\` はバッファの先頭にのみマッチする。

\' はバッファの終端にのみマッチする。

\A はバッファの先頭にのみマッチする(\` と同じ)。

\z はバッファの終端にのみマッチする(\' と同じ)。

\Z はバッファ終端における省略可能な改行シーケンスのゼロ幅表明にマッチする。正規表現:regexp:(?=\v*\z) と等価である。(?=\n?\z) のような動作をする Perl とは微妙に異なることに注意していただきたい。

継続エスケープ(Continuation Escape)

シーケンス \G は最後にマッチが見つかった位置、あるいは前回のマッチが存在しない場合はマッチ対象テキストの先頭にのみマッチする。各マッチが 1 つ前のマッチの終端から始まっているようなマッチをテキスト中から列挙する場合に、このシーケンスは有効である。

クォーティングエスケープ(Quoting Escape)

エスケープシーケンス \Q は「クォートされたシーケンス」の開始を表す。以降、正規表現の終端か \E までの文字はすべて直値として扱われる。例えば、正規表現 \Q\*+\Ea+ は以下のいずれかにマッチする。

\*+a
\*+aaa

Unicode エスケープ

\C は単一のコードポイントにマッチする。Boost.Regex では . 演算子とまったく同じ意味である。\X は結合文字シーケンス(非結合文字に 0 以上の結合文字シーケンスが続く)にマッチする。

行末へのマッチ

エスケープシーケンス \R はあらゆる改行文字シーケンスにマッチする。つまり、式 (?>\x0D\x0A?|[\x0A-\x0C\x85\x{2028}\x{2029}]) と等価である。

テキストの除外

\K は $0 の開始位置を現在のテキスト位置にリセットする。言い換えると \K より前にあるものはすべて差し引かれ、正規表現マッチの一部とならない。$` も同様に更新される。

例えば foo\Kbar をテキスト foobar にマッチさせると、$0 に対して bar 、$` に対して foo というマッチ結果が返る。これは可変幅の後方先読みを再現するのに使用する。

その他のエスケープ

その他のエスケープシーケンスは、エスケープ対象の文字そのものにマッチする。例えば \@ は直値 @ にマッチする。

Perl の拡張パターン

正規表現構文の Perl 固有の拡張はすべて (? で始まる。

名前付き部分式

以下のようにして部分式を作成する。

(?<NAME>expression)

これで NAME という名前で参照可能になる。あるいは以下の 'NAME' のように区切り文字を使う方法もある。

(?'NAME'expression)

これらの名前付き部分式は後方参照内で \g{NAME}\k<NAME> で参照する。検索・置換操作で使用する Perl 形式の文字列、および match_results メンバ関数では名前で参照する。

注釈

(?# ... ) は注釈(コメント)として扱われ、内容は無視される。

修飾子

(?imsx-imsx ... ) は、パターン中でどの Perl 修飾子を有効にするかを設定する。効果はブロックの先頭から閉じ括弧)までである。- より前にある文字が Perl 修飾子を有効にし、後にある文字が無効にする。

(?imsx-imsx:pattern) は、指定した修飾子をパターンのみに適用する。

マークなしのグループ

(?:pattern) は、パターンを字句的にグループ化する。部分式の生成はない。

選択分岐ごとの部分式番号のリセット(Branch reset)

(?|pattern) は、pattern 内において | が現れるごとに部分式の番号をリセットする。

この構造の後ろの部分式番号は、部分式の数が最大である選択分岐により決定する。この構造は、複数の選択マッチから 1 つを単一の部分式添字で捕捉したい場合に有効である。

以下に例を示す。式の下にあるのが各部分式の添字である。

# before  ---------------branch-reset----------- after
/ ( a )  (?| x ( y ) z | (p (q) r) | (t) u (v) ) ( z ) /x
# 1            2         2  3        2     3     4

先読み

(?=pattern) はパターンがマッチした場合に限り、現在位置を進めない。

(?!pattern) はパターンがマッチしなかった場合に限り、現在位置を進めない。

先読みを使用する典型的な理由は、2 つの正規表現の論理和作成である。例えばパスワードが大文字、小文字、区切り記号を含み、6 文字以上でなければならないとすると、次の正規表現でパスワードを検証できる。

(?=.*[[:lower:]])(?=.*[[:upper:]])(?=.*[[:punct:]]).{6,}

後読み

(?<=pattern) は、現在位置の直前の文字列がパターンにマッチ可能な場合に限り、現在位置を進めない(パターンは固定長でなければならない)。

(?<!pattern) は、現在位置の直前の文字列がパターンにマッチ不能な場合に限り、現在位置を進めない(パターンは固定長でなければならない)。

独立部分式

(?>pattern) とすると、pattern は周囲のパターンとは独立してマッチし、正規表現は pattern にはバックトラックしない。独立部分式を使用する典型的な理由は効率の向上である。可能な限り最良のマッチのみが考慮されるため、独立部分式が正規表現全体のマッチを妨害する場合はマッチは 1 つも見つからない。 2

再帰式

(?N) (?-N) (?+N) (?R) (?0)

(?R) および (?0) はパターン全体の先頭に再帰する。

(?N)N 番目の部分式を再帰的に実行する。例えば (?2) は 2 番目の部分式へ再帰する。

(?-N) および (?+N) は相対的な再帰である。例えば (?-1) は最後の部分式へ、(?+1) は次の部分式へ再帰する。

条件式

(?(condition)yes-pattern|no-pattern) は、condition が真であれば yes-pattern 、それ以外の場合は no-pattern のマッチを行う。

(?(condition)yes-pattern) は、condition が真であれば yes-pattern のマッチを行い、それ以外の場合は空文字列にマッチする。

condition は前方先読み表明、マーク済み部分式の添字(対応する部分式がマッチしていれば条件が真)、あるいは再帰式の添字(指定した再帰式内を直接実行している場合に条件が真)のいずれかである。

考えられる条件式を挙げる。

  • (?(?=assert)yes-pattern|no-pattern) は、前方先読み表明がマッチした場合に yes-pattern を、それ以外の場合に no-pattern を実行する。

  • (?(?!assert)yes-pattern|no-pattern) は、前方先読み表明がマッチしなかった場合に yes-pattern を、それ以外の場合に no-pattern を実行する。

  • (?(N)yes-pattern|no-pattern) は、N 番目の部分式がマッチした場合に yes-pattern を、それ以外の場合に no-pattern を実行する。

  • (?(<name>)yes-pattern|no-pattern) は、名前付き部分式 name がマッチした場合に yes-pattern を、それ以外の場合に no-pattern を実行する。

  • (?('name')yes-pattern|no-pattern) は、名前付き部分式 name がマッチした場合に yes-pattern を、それ以外の場合に no-pattern を実行する。

  • (?(R)yes-pattern|no-pattern) は、再帰式内を実行中である場合に yes-pattern を、それ以外の場合に no-pattern を実行する。

  • (?(RN)yes-pattern|no-pattern) は、N 番目の部分式への再帰内を実行中である場合に yes-pattern を、それ以外の場合に no-pattern を実行する。

  • (?(R&name)yes-pattern|no-pattern) は、名前付き部分式 name への再帰内を実行中である場合に yes-pattern を、それ以外の場合に no-pattern を実行する。

  • (?(DEFINE)never-executed-pattern) は絶対に実行されず、どこにもマッチしないコードブロックを定義する。通常、パターン内の別の場所から参照する 1 つ以上の名前付き式を定義するのに使用する。

バックトラッキング制御動詞

本ライブラリは Perl のバックトラッキング制御動詞をサポートする。ただし部分的なものであり、特に (*MARK) はサポートしない。本ライブラリと Perl の間では細かい挙動が異なる可能性がある。少なくとも Perl の挙動はドキュメントが不十分であり、実際にはよく分からない動作をすることがあるからである。サポートしている動詞は以下のとおり。

(*PRUNE)

バックトラックしてきた場合に、それ以前のバックトラッキングに関するすべての情報を破棄する。これ以外の場合では作用は無い。

(*SKIP)

(*PRUNE) と同じだが、検索対象文字列における現在位置より前でマッチが発生しないことを示す点が異なる。すでにマッチを構成しないと決定したテキストのチャンクをスキップすることで検索を最適化するのに使用する。

(*THEN)

バックトラックしてきた場合に、選択グループ内の残りすべての選択を破棄する。これ以外の場合では作用は無い。

(*COMMIT)

バックトラックしてきた場合に、残りすべてのマッチと検索を失敗させる。これ以外の場合では作用は無い。

(*FAIL)

この時点で無条件にマッチを失敗させる。正規表現エンジンにバックトラックを強制するのに使用する。

(*ACCEPT)

この時点でパターンがマッチしたとする。半開きの部分式はすべてその時点で閉じられる。

演算子の優先順位

演算子の優先順位は以下のとおりである。

  1. 照合関係の括弧記号 [==] [::] [..]

  2. エスケープ \

  3. 文字集合(括弧式) []

  4. グループ ()

  5. 単一文字の繰り返し * + ? {m,n}

  6. 結合

  7. アンカー ^$

  8. 選択 |

マッチするもの

正規表現を有向グラフ(あるいは閉路グラフ)とみなすと、入力テキストに対する最良マッチとは、グラフに対して深さ優先検索を行って最初に見つかるマッチである。

これは言い換えると次のようになる。最良マッチとは各要素が以下のようにマッチする最左マッチである。

構造

マッチするもの

AtomA AtomB

AtomB に対するマッチが直後に続く AtomA に対する最良マッチを検索する。

ExpressionA | ExpressionB

Expression1 がマッチ可能であればそのマッチを返す。それ以外の場合は Expression2 を試行する。

S{N}

S のちょうど N 回の繰り返しにマッチする。

S{N,M}

S の、N 回以上 M 回以下の可能な限り長い繰り返しにマッチする。

S{N,M}?

S の、N 回以上 M 回以下の可能な限り短い繰り返しにマッチする。

S?S*S+

それぞれ S{0,1}S{0,UINT_MAX}S{1,UINT_MAX} と同じ。

S??S*?S+?

それぞれ S{0,1}?S{0,UINT_MAX}?S{1,UINT_MAX}? と同じ。

(?>S)

S の最良マッチにマッチするのみ。

(?=S)(?<=S)

S の最良マッチにのみマッチする(これが分かるのは、S 中に捕捉を行う括弧がある場合のみ)。

(?!S)(?<!S)

S に対するマッチが存在するかどうか考慮するのみ。

(?(condition)yes-pattern|no-pattern)

条件が真であれば yes-pattern のみが考慮される。それ以外の場合は no-pattern のみが考慮される。

バリエーション

normalECMAScriptJavaScript および JScript各オプションはすべて perl の別名である。

オプション

正規表現構築時に perl オプションとともに指定可能なフラグが多数ある。特に collateno_subsicase オプションが大文字小文字の区別やロカール依存の動作を変更するのに対し、newline_alt オプションは構文を変更するという点に注意していただきたい。

パターン修飾子

(?smix-smix) を正規表現の前につけるか、正規表現コンパイル時フラグ no_mod_mmod_xmod_sno_mod_s を使用することで Perl の smix 修飾子を適用することができる。

参考

Perl 5.83

1

訳注 独立部分式の知識がある方でなければ意味不明だと思います。Perl のチュートリアル等を参照されることをお勧めします。

2

訳注 テーラリング(tailoring)は汎用的な処理に対して、特定の事情に即した結果を得るために追加規則を用いて処理をカスタマイズすることを意味します。文字処理の分野では特に各ロカールに対応するためのテーラリングが多数存在します。

3

訳注 リンク先はバージョン 5 系列の最新版になっています。現在の Boost.Regex には Perl 5.9 以降の機能が追加されているので、確認しておくといいです。