名前空間
変種
操作

ECMAScript 修正正規表現文法

From cppreference.com
< cpp‎ | regex
 
 
 
正規表現ライブラリ
クラス
(C++11)
アルゴリズム
イテレータ
例外
Traits
定数
(C++11)
正規表現文法
修正ECMAScript-262
(C++11)
 

このページは、std::basic_regexsyntax_option_typeECMAScript (デフォルト) を設定して構築されたときに使用される正規表現文法について説明します。サポートされている他の正規表現文法については syntax_option_type を参照してください。

C++における ECMAScript 3 の正規表現文法は、ECMA-262 文法に、以下で (C++ only) とマークされた修正を加えたものです。

目次

[編集] 概要

修正正規表現文法は、ほとんどが ECMAScript RegExp 文法であり、ClassAtom の下でロケールに関する POSIX 型の拡張が加えられています。等価性チェックと数値のパースに関するいくつかの明確化がなされています。ここにある多くの例については、ブラウザのコンソールで同等のものを試すことができます。

function match(s, re) { return s.match(new RegExp(re)); }

標準規格の「引用規格」では ECMAScript 3 が指定されています。ここでは ECMAScript 5.1 の仕様にリンクしていますが、これは ECMAScript 3 からの変更点が少なく、HTML 版が存在するためです。この方言の機能の概要については、MDN の JavaScript RegExp ガイドを参照してください。

[編集] 代替 (Alternatives)

正規表現パターンは、選言演算子 | で区切られた1つ以上の Alternative のシーケンスです(言い換えれば、選言演算子は最も低い優先順位を持ちます)。

パターン (Pattern) ::

選言 (Disjunction)

選言 (Disjunction) ::

代替 (Alternative)
Alternative | Disjunction

パターンは、まず Disjunction をスキップし、左の Alternative にマッチさせ、その後に正規表現の残り(Disjunction の後)をマッチさせようと試みます。

失敗した場合、左の Alternative をスキップし、右の Disjunction にマッチさせようと試みます(その後に正規表現の残りが続きます)。

左の Alternative、右の Disjunction、および正規表現の残りの部分がすべて選択点を持つ場合、式の残りの部分のすべての選択肢が試された後、左の Alternative の次の選択肢に移ります。左の Alternative の選択肢が尽きた場合、左の Alternative の代わりに右の Disjunction が試されます。

スキップされた Alternative 内のキャプチャ括弧は、空のサブマッチを生成します。

#include <cstddef>
#include <iostream>
#include <regex>
#include <string>
 
void show_matches(const std::string& in, const std::string& re)
{
    std::smatch m;
    std::regex_search(in, m, std::regex(re));
    if (!m.empty())
    {
        std::cout << "input=[" << in << "], regex=[" << re << "]\n  "
                     "prefix=[" << m.prefix() << "]\n  smatch: ";
        for (std::size_t n = 0; n < m.size(); ++n)
            std::cout << "m[" << n << "]=[" << m[n] << "] ";
        std::cout << "\n  suffix=[" << m.suffix() << "]\n";
    }
    else
        std::cout << "input=[" << in << "], regex=[" << re << "]: NO MATCH\n";
}
 
int main()
{
    show_matches("abcdef", "abc|def");
    show_matches("abc", "ab|abc"); // left Alternative matched first
 
    // Match of the input against the left Alternative (a) followed
    // by the remained of the regex (c|bc) succeeds, which results
    // in m[1]="a" and m[4]="bc".
    // The skipped Alternatives (ab) and (c) leave their submatches
    // m[3] and m[5] empty.
    show_matches("abc", "((a)|(ab))((c)|(bc))");
}

出力

input=[abcdef], regex=[abc|def]
  prefix=[]
  smatch: m[0]=[abc]
  suffix=[def]
input=[abc], regex=[ab|abc]
  prefix=[]
  smatch: m[0]=[ab]
  suffix=[c]
input=[abc], regex=[((a)|(ab))((c)|(bc))]
  prefix=[]
  smatch: m[0]=[abc] m[1]=[a] m[2]=[a] m[3]=[] m[4]=[bc] m[5]=[] m[6]=[bc]
  suffix=[]

[編集] 項 (Terms)

Alternative は、空であるか、または Term のシーケンスです(Term の間に区切り文字はありません)。

代替 (Alternative) ::

[空]
Alternative Term

空の Alternative は常にマッチし、入力を消費しません。

連続する Term は、入力の連続する部分に同時にマッチしようと試みます。

左の Alternative、右の Term、および正規表現の残りの部分がすべて選択点を持つ場合、式の残りの部分のすべての選択肢が試された後、右の Term の次の選択肢に移ります。そして、右の Term のすべての選択肢が試された後、左の Alternative の次の選択肢に移ります。

#include <cstddef>
#include <iostream>
#include <regex>
#include <string>
 
void show_matches(const std::string& in, const std::string& re)
{
    std::smatch m;
    std::regex_search(in, m, std::regex(re));
    if (!m.empty())
    {
        std::cout << "input=[" << in << "], regex=[" << re << "]\n  "
                     "prefix=[" << m.prefix() << "]\n  smatch: ";
        for (std::size_t n = 0; n < m.size(); ++n)
            std::cout << "m[" << n << "]=[" << m[n] << "] ";
        std::cout << "\n  suffix=[" << m.suffix() << "]\n";
    }
    else
        std::cout << "input=[" << in << "], regex=[" << re << "]: NO MATCH\n";
}
 
int main()
{
    show_matches("abcdef", ""); // empty regex is a single empty Alternative
    show_matches("abc", "abc|"); // left Alternative matched first
    show_matches("abc", "|abc"); // left Alternative matched first, leaving abc unmatched
}

出力

input=[abcdef], regex=[]
  prefix=[]
  smatch: m[0]=[]
  suffix=[abcdef]
input=[abc], regex=[abc|]
  prefix=[]
  smatch: m[0]=[abc]
  suffix=[]
input=[abc], regex=[|abc]
  prefix=[]
  smatch: m[0]=[]
  suffix=[abc]

[編集] 量指定子 (Quantifiers)

  • Term は、Assertion(下記参照)、Atom(下記参照)、または Atom の直後に Quantifier が続くもののいずれかです。

項 (Term) ::

アサーション (Assertion)
アトム (Atom)
Atom Quantifier

Quantifier は、greedy(貪欲)な量指定子(1つの QuantifierPrefix のみで構成)または non-greedy(非貪欲)な量指定子(1つの QuantifierPrefix の後にクエスチョンマーク ? が続く)のいずれかです。

量指定子 (Quantifier) ::

量指定子接頭辞 (QuantifierPrefix)
QuantifierPrefix ?

QuantifierPrefix は、2つの数値を決定します。最小繰り返し回数と最大繰り返し回数で、以下の通りです。

量指定子接頭辞 (QuantifierPrefix) 最小 最大
* 0 infinity
+ 1 infinity
? 0 1
{ DecimalDigits } DecimalDigits の値 DecimalDigits の値
{ DecimalDigits , } DecimalDigits の値 infinity
{ DecimalDigits , DecimalDigits } コンマの前の DecimalDigits の値 コンマの後の DecimalDigits の値

個々の DecimalDigits の値は、各数字に対して std::regex_traits::value(C++ only) を呼び出すことで得られます。

Quantifier が続く Atom は、Quantifier によって指定された回数だけ繰り返されます。Quantifiernon-greedy(非貪欲)にすることができ、その場合 Atom パターンは正規表現の残りの部分にマッチしつつ可能な限り少なく繰り返されます。あるいは greedy(貪欲)にすることもでき、その場合 Atom パターンは正規表現の残りの部分にマッチしつつ可能な限り多く繰り返されます。

繰り返されるのは Atom パターンであり、それにマッチした入力ではありません。そのため、Atom の異なる繰り返しは異なる入力部分文字列にマッチすることがあります。

Atom と正規表現の残りの部分がすべて選択点を持つ場合、Atom はまず可能な限り多く(non-greedy の場合は少なく)マッチされます。正規表現の残りの部分のすべての選択肢が試された後、Atom の最後の繰り返しの次の選択肢に移ります。Atom の最後の(n番目の)繰り返しのすべての選択肢が試された後、最後から2番目(n-1番目)の繰り返しの次の選択肢に移ります。その時点で、より多い、またはより少ない Atom の繰り返しが可能になることがあり、これらが(再び、可能な限り少ない、または多い回数から始めて)尽きるまで試された後、(n-1)番目の繰り返しの次の選択肢に移り、以下同様に続きます。

Atom のキャプチャは、繰り返されるたびにクリアされます(下記の "(z)((a+)?(b+)?(c))*" の例を参照)。

#include <cstddef>
#include <iostream>
#include <regex>
#include <string>
 
void show_matches(const std::string& in, const std::string& re)
{
    std::smatch m;
    std::regex_search(in, m, std::regex(re));
    if (!m.empty())
    {
        std::cout << "input=[" << in << "], regex=[" << re << "]\n  "
                     "prefix=[" << m.prefix() << "]\n  smatch: ";
        for (std::size_t n = 0; n < m.size(); ++n)
            std::cout << "m[" << n << "]=[" << m[n] << "] ";
        std::cout << "\n  suffix=[" << m.suffix() << "]\n";
    }
    else
        std::cout << "input=[" << in << "], regex=[" << re << "]: NO MATCH\n";
}
 
int main()
{
    // greedy match, repeats [a-z] 4 times
    show_matches("abcdefghi", "a[a-z]{2,4}");
    // non-greedy match, repeats [a-z] 2 times
    show_matches("abcdefghi", "a[a-z]{2,4}?");
 
    // Choice point ordering for quantifiers results in a match
    // with two repetitions, first matching the substring "aa",
    // second matching the substring "ba", leaving "ac" not matched
    // ("ba" appears in the capture clause m[1])
    show_matches("aabaac", "(aa|aabaac|ba|b|c)*");
 
    // Choice point ordering for quantifiers makes this regex 
    // calculate the greatest common divisor between 10 and 15
    // (the answer is 5, and it populates m[1] with "aaaaa")
    show_matches("aaaaaaaaaa,aaaaaaaaaaaaaaa", "^(a+)\\1*,\\1+$");
 
    // the substring "bbb" does not appear in the capture clause m[4]
    // because it is cleared when the second repetition of the atom
    // (a+)?(b+)?(c) is matching the substring "ac"
    // NOTE: gcc gets this wrong - it does not correctly clear the
    // matches[4] capture group as required by ECMA-262 21.2.2.5.1,
    // and thus incorrectly captures "bbb" for that group.
    show_matches("zaacbbbcac", "(z)((a+)?(b+)?(c))*");
}

出力

input=[abcdefghi], regex=[a[a-z]{2,4}]
  prefix=[]
  smatch: m[0]=[abcde]
  suffix=[fghi]
input=[abcdefghi], regex=[a[a-z]{2,4}?]
  prefix=[]
  smatch: m[0]=[abc]
  suffix=[defghi]
input=[aabaac], regex=[(aa|aabaac|ba|b|c)*]
  prefix=[]
  smatch: m[0]=[aaba] m[1]=[ba]
  suffix=[ac]
input=[aaaaaaaaaa,aaaaaaaaaaaaaaa], regex=[^(a+)\1*,\1+$]
  prefix=[]
  smatch: m[0]=[aaaaaaaaaa,aaaaaaaaaaaaaaa] m[1]=[aaaaa]
  suffix=[]
input=[zaacbbbcac], regex=[(z)((a+)?(b+)?(c))*]
  prefix=[]
  smatch: m[0]=[zaacbbbcac] m[1]=[z] m[2]=[ac] m[3]=[a] m[4]=[] m[5]=[c] 
  suffix=[]

[編集] アサーション (Assertions)

Assertion(アサーション)は、入力文字列の部分文字列ではなく、条件にマッチします。これらは入力から文字を消費することはありません。各 Assertion は以下のいずれかです。

アサーション (Assertion) ::

^
$
\ b
\ B
( ? = Disjunction )
( ? ! Disjunction )

アサーション ^(行頭)は以下にマッチします。

1) LineTerminator(行終端文字)の直後の位置 (サポートされていない可能性があります)(C++17まで)std::regex_constants::multiline(C++ only) が有効な場合にのみ保証されます)(C++17から)
2) 入力の先頭(std::regex_constants::match_not_bol(C++ only) が有効な場合を除く)

アサーション $(行末)は以下にマッチします。

1) LineTerminator(行終端文字)の位置 (サポートされていない可能性があります)(C++17まで)std::regex_constants::multiline(C++ only) が有効な場合にのみ保証されます)(C++17から)
2) 入力の末尾(std::regex_constants::match_not_eol(C++ only) が有効な場合を除く)

上記の2つのアサーションおよび下記のアトム . において、LineTerminator とは以下の4つの文字のいずれかです:U+000A\n またはラインフィード)、U+000D\r またはキャリッジリターン)、U+2028(ラインセパレータ)、または U+2029(パラグラフセパレータ)

アサーション \b(単語境界)は以下にマッチします。

1) 単語の先頭(現在の文字が英字、数字、またはアンダースコアで、前の文字がそうでない場合)
2) 単語の末尾(現在の文字が英字、数字、またはアンダースコアでなく、前の文字がそれらのいずれかである場合)
3) 最初の文字が英字、数字、またはアンダースコアである場合の入力の先頭(std::regex_constants::match_not_bow(C++ only) が有効な場合を除く)
4) 最後の文字が英字、数字、またはアンダースコアである場合の入力の末尾(std::regex_constants::match_not_eow(C++ only) が有効な場合を除く)

アサーション \B(非単語境界)は、以下を除くすべてにマッチします。

1) 単語の先頭(現在の文字が英字、数字、またはアンダースコアで、前の文字がそれらのいずれでもないか、存在しない場合)
2) 単語の末尾(現在の文字が英字、数字、またはアンダースコアでなく(またはマッチャーが入力の末尾にある場合)、前の文字がそれらのいずれかである場合)

アサーション ( ? = Disjunction )(ゼロ幅の肯定先読み)は、現在の位置で Disjunction が入力にマッチする場合にマッチします。

アサーション ( ? ! Disjunction )(ゼロ幅の否定先読み)は、現在の位置で Disjunction が入力にマッチしない場合にマッチします。

両方の先読みアサーションにおいて、Disjunction にマッチさせる際、正規表現の残りの部分にマッチさせる前に位置は進められません。また、Disjunction が現在の位置で複数の方法でマッチできる場合でも、最初のものだけが試されます。

ECMAScript は先読みの Disjunction へのバックトラックを禁止しており、これは正規表現の残りから肯定先読みへの後方参照の動作に影響します(下記の例を参照)。正規表現の残りから否定先読みへの後方参照は常に未定義です(先読みの Disjunction は処理を進めるために失敗しなければならないため)。

注:先読みアサーションは、複数の正規表現の間で論理 AND を作成するために使用できます(下記の例を参照)。

#include <cstddef>
#include <iostream>
#include <regex>
#include <string>
 
void show_matches(const std::string& in, const std::string& re)
{
    std::smatch m;
    std::regex_search(in, m, std::regex(re));
    if (!m.empty())
    {
        std::cout << "input=[" << in << "], regex=[" << re << "]\n  "
                     "prefix=[" << m.prefix() << "]\n  smatch: ";
        for (std::size_t n = 0; n < m.size(); ++n)
            std::cout << "m[" << n << "]=[" << m[n] << "] ";
        std::cout << "\n  suffix=[" << m.suffix() << "]\n";
    }
    else
        std::cout << "input=[" << in << "], regex=[" << re << "]: NO MATCH\n";
}
 
int main()
{
    // matches the a at the end of input
    show_matches("aaa", "a$");
 
    // matches the o at the end of the first word
    show_matches("moo goo gai pan", "o\\b");
 
    // the lookahead matches the empty string immediately after the first b
    // this populates m[1] with "aaa" although m[0] is empty
    show_matches("baaabac", "(?=(a+))");
 
    // because backtracking into lookaheads is prohibited, 
    // this matches aba rather than aaaba
    show_matches("baaabac", "(?=(a+))a*b\\1");
 
    // logical AND via lookahead: this password matches IF it contains
    // at least one lowercase letter
    // AND at least one uppercase letter
    // AND at least one punctuation character
    // AND be at least 6 characters long
    show_matches("abcdef", "(?=.*[[:lower:]])(?=.*[[:upper:]])(?=.*[[:punct:]]).{6,}");
    show_matches("aB,def", "(?=.*[[:lower:]])(?=.*[[:upper:]])(?=.*[[:punct:]]).{6,}");
}

出力

input=[aaa], regex=[a$]
  prefix=[aa]
  smatch: m[0]=[a] 
  suffix=[]
input=[moo goo gai pan], regex=[o\b]
  prefix=[mo]
  smatch: m[0]=[o] 
  suffix=[ goo gai pan]
input=[baaabac], regex=[(?=(a+))]
  prefix=[b]
  smatch: m[0]=[] m[1]=[aaa] 
  suffix=[aaabac]
input=[baaabac], regex=[(?=(a+))a*b\1]
  prefix=[baa]
  smatch: m[0]=[aba] m[1]=[a] 
  suffix=[c]
input=[abcdef], regex=[(?=.*[[:lower:]])(?=.*[[:upper:]])(?=.*[[:punct:]]).{6,}]: NO MATCH
input=[aB,def], regex=[(?=.*[[:lower:]])(?=.*[[:upper:]])(?=.*[[:punct:]]).{6,}]
  prefix=[]
  smatch: m[0]=[aB,def] 
  suffix=[]

[編集] アトム (Atoms)

Atom は以下のいずれかです。

アトム (Atom) ::

パターン文字 (PatternCharacter)
.
\ AtomEscape
文字クラス (CharacterClass)
( Disjunction )
( ? : Disjunction )

ここで AtomEscape は:

10進エスケープ (DecimalEscape)
文字エスケープ (CharacterEscape)
文字クラスエスケープ (CharacterClassEscape)

異なる種類のアトムは、異なる方法で評価されます。

[編集] 部分式

アトム ( Disjunction ) は、マーク付き部分式です。これは Disjunction を実行し、Disjunction によって消費された入力部分文字列のコピーをサブマッチ配列に格納します。格納先のインデックスは、その時点までに正規表現全体でマーク付き部分式の左開き括弧 ( が出現した回数に対応します。

std::match_results で返されるだけでなく、キャプチャされたサブマッチは後方参照(\1\2、...)としてアクセス可能であり、正規表現内で参照できます。注意点として、std::regex_replace は、String.prototype.replace(ECMA-262、パート15.5.4.11)と同様に、後方参照に \ の代わりに $ を使用します($1$2、...)。

アトム ( ? : Disjunction )(非マーク付き部分式)は、単に Disjunction を評価し、その結果をサブマッチに格納しません。これは純粋に字句的なグループ化です。

[編集] 後方参照

10進エスケープ (DecimalEscape) ::

DecimalIntegerLiteral [lookaheadDecimalDigit]

\ の後に、最初の桁が 0 ではない10進数 N が続く場合、そのエスケープシーケンスは backreference(後方参照)と見なされます。値 N は、各数字に対して std::regex_traits::value(C++ only) を呼び出し、その結果を10進数の演算で結合して得られます。N が正規表現全体の左キャプチャ括弧の総数より大きい場合、エラーとなります。

後方参照 \NAtom として現れる場合、それはサブマッチ配列の N 番目の要素に現在格納されているものと同じ部分文字列にマッチします。

10進エスケープ \0 は後方参照ではありません。これは NUL 文字を表す文字エスケープです。その後に10進数字を続けることはできません。

前述の通り、std::regex_replace は後方参照に \ の代わりに $ を使用することに注意してください($1$2、...)。

[編集] 単一文字マッチ

アトム . は、LineTerminatorU+000DU+000AU+2029、または U+2028)を除く入力文字列から任意の1文字にマッチし、消費します。

アトム PatternCharacter は、PatternCharacter^ $ \ . * + ? ( ) [ ] { } | の文字を除く任意の SourceCharacter である場合、入力から1文字を、それがこの PatternCharacter と等しい場合にマッチさせ、消費します。

これおよび他のすべての単一文字マッチの等価性は、以下のように定義されます。

1) std::regex_constants::icase が設定されている場合、std::regex_traits::translate_nocase の戻り値が等しい場合に文字は等しいと見なされます (C++ only)
2) そうでなく、std::regex_constants::collate が設定されている場合、std::regex_traits::translate の戻り値が等しい場合に文字は等しいと見なされます (C++ only)
3) それ以外の場合、operator==true を返す場合に文字は等しいと見なされます。

エスケープ文字 \ とそれに続く CharacterEscape、および特殊な10進エスケープ \0 からなる各 Atom は、CharacterEscape によって表される文字と等しい場合に入力から1文字をマッチさせ、消費します。以下の文字エスケープシーケンスが認識されます。

文字エスケープ (CharacterEscape) ::

制御エスケープ (ControlEscape)
c ControlLetter
16進エスケープシーケンス (HexEscapeSequence)
Unicodeエスケープシーケンス (UnicodeEscapeSequence)
同一エスケープ (IdentityEscape)

ここで、ControlEscape は以下の5つの文字のいずれかです:f n r t v

制御エスケープ (ControlEscape) コード単位 名前
f U+000C フォームフィード
n U+000A 改行
r U+000D キャリッジリターン
t U+0009 水平タブ
v U+000B 垂直タブ

ControlLetter は任意の小文字または大文字の ASCII 文字であり、この文字エスケープは、ControlLetter のコード単位の値を 32 で割った余りに等しいコード単位を持つ文字にマッチします。例えば、\cD\cd は両方ともコード単位 U+0004 (EOT) にマッチします。なぜなら、'D' は U+00440x44 % 32 == 4 であり、'd' は U+00640x64 % 32 == 4 だからです。

HexEscapeSequence は、文字 x に続いてちょうど2つの HexDigitHexDigit0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F のいずれか)が来るものです。この文字エスケープは、2桁の16進数の数値に等しいコード単位を持つ文字にマッチします。

UnicodeEscapeSequence は、文字 u に続いてちょうど4つの HexDigit が来るものです。この文字エスケープは、4桁の16進数の数値に等しいコード単位を持つ文字にマッチします。この値がこの std::basic_regexCharT に収まらない場合、std::regex_error がスローされます (C++ only)

IdentityEscape は、任意の非英数字にすることができます。例えば、もう一つのバックスラッシュです。これはその文字自身にマッチします。

#include <cstddef>
#include <iostream>
#include <regex>
#include <string>
 
void show_matches(const std::wstring& in, const std::wstring& re)
{
    std::wsmatch m;
    std::regex_search(in, m, std::wregex(re));
    if (!m.empty())
    {
        std::wcout << L"input=[" << in << L"], regex=[" << re << L"]\n  "
                      L"prefix=[" << m.prefix() << L"]\n  wsmatch: ";
        for (std::size_t n = 0; n < m.size(); ++n)
            std::wcout << L"m[" << n << L"]=[" << m[n] << L"] ";
        std::wcout << L"\n  suffix=[" << m.suffix() << L"]\n";
    }
    else
        std::wcout << L"input=[" << in << "], regex=[" << re << L"]: NO MATCH\n";
}
 
int main()
{
    // Most escapes are similar to C++, save for metacharacters. You will have to
    // double-escape or use raw strings on the slashes though.
    show_matches(L"C++\\", LR"(C\+\+\\)");
 
    // Escape sequences and NUL.
    std::wstring s(L"ab\xff\0cd", 5);
    show_matches(s, L"(\\0|\\u00ff)");
 
    // No matching for non-BMP Unicode is defined, because ECMAScript uses UTF-16
    // atoms. Whether this emoji banana matches can be platform dependent:
    // These need to be wide-strings!
    show_matches(L"\U0001f34c", L"[\\u0000-\\ufffe]+");
}

実行結果の例

input=[C++\], regex=[C\+\+\\]
  prefix=[]
  wsmatch: m[0]=[C++\]
  suffix=[]
input=[ab?c], regex=[(\0{{!}}\u00ff)]
  prefix=[ab]
  wsmatch: m[0]=[?] m[1]=[?]
  suffix=[c]
input=[?], regex=[[\u0000-\ufffe]+]: NO MATCH

[編集] 文字クラス

アトムは文字クラスを表すことができ、その場合、事前定義された文字グループのいずれかに属する1文字にマッチし、消費します。

文字クラスは、文字クラスエスケープを介して導入できます。

アトム (Atom) ::

\ CharacterClassEscape

または直接

アトム (Atom) ::

文字クラス (CharacterClass)

文字クラスエスケープは、いくつかの一般的な文字クラスの短縮形であり、以下の通りです。

文字クラスエスケープ (CharacterClassEscape) クラス名式(C++ only) 意味
d [[:digit:]] digits
D [^[:digit:]] 非数字
s [[:space:]] 空白文字
S [^[:space:]] 非空白文字
w [_[:alnum:]] 英数字と文字 _
W [^_[:alnum:]] 英数字または _ 以外の文字
C++におけるこれらの各文字クラスエスケープの正確な意味は、ECMAScript のように許容される文字を明示的にリストアップするのではなく、ロケールに依存する名前付き文字クラスの観点から定義されます。

CharacterClass は、角括弧で囲まれた ClassRanges のシーケンスであり、オプションで否定演算子 ^ で始まることができます。^ で始まる場合、この Atom は、すべての ClassRanges の和集合で表される文字集合に「含まれない」任意の文字にマッチします。それ以外の場合、この Atom は、すべての ClassRanges の和集合で表される文字集合に「含まれる」任意の文字にマッチします。

文字クラス (CharacterClass) ::

[ [ lookahead ∉ {^}] ClassRanges ]
[ ^ ClassRanges ]

ClassRanges :

[空]
NonemptyClassRanges

NonemptyClassRanges ::

ClassAtom
ClassAtom NonemptyClassRangesNoDash
ClassAtom - ClassAtom ClassRanges

空でないクラス範囲が ClassAtom - ClassAtom の形式を持つ場合、それは以下のように定義される範囲内の任意の文字にマッチします: (C++ only)

最初の ClassAtom は単一の照合要素 c1 にマッチし、2番目の ClassAtom は単一の照合要素 c2 にマッチしなければなりません。入力文字 c がこの範囲にマッチするかをテストするために、以下のステップが実行されます。

1) std::regex_constants::collate がオンでない場合、文字はコードポイントの直接比較によってマッチングされます:c1 <= c && c <= c2 であれば c はマッチします。
1) そうでない場合(std::regex_constants::collate が有効な場合)
1) std::regex_constants::icase が有効な場合、3つの文字(c, c1, c2)はすべて std::regex_traits::translate_nocase に渡されます。
2) そうでない場合(std::regex_constants::icase が設定されていない場合)、3つの文字(c, c1, c2)はすべて std::regex_traits::translate に渡されます。
2) 結果の文字列は std::regex_traits::transform を用いて比較され、transformed c1 <= transformed c && transformed c <= transformed c2 であれば文字 c はマッチします。

文字 - は、以下の場合にリテラルとして扱われます。

  • ClassRanges の最初または最後の文字である場合
  • ダッシュで区切られた範囲指定の開始または終了の ClassAtom である場合
  • ダッシュで区切られた範囲指定の直後に続く場合
  • CharacterEscape としてバックスラッシュでエスケープされている場合

NonemptyClassRangesNoDash :

ClassAtom
ClassAtomNoDash NonemptyClassRangesNoDash
ClassAtomNoDash - ClassAtom ClassRanges

ClassAtom ::

-
ClassAtomNoDash
ClassAtomExClass(C++ only)
ClassAtomCollatingElement(C++ only)
ClassAtomEquivalence(C++ only)

ClassAtomNoDash :

\ or ] or - のいずれでもない SourceCharacter
\ ClassEscape

ClassAtomNoDash は、単一の文字を表します — SourceCharacter そのものか、または以下のようにエスケープされたものです。

ClassEscape :

10進エスケープ (DecimalEscape)
b
文字エスケープ (CharacterEscape)
文字クラスエスケープ (CharacterClassEscape)

特殊な ClassEscape \b は、コード単位 U+0008(バックスペース)にマッチする文字集合を生成します。CharacterClass の外では、これは単語境界の Assertion です。

CharacterClass 内で \B を使用すること、および任意の後方参照(0以外の DecimalEscape)を使用することはエラーです。

文字 -] は、アトムとして扱われるために、状況によってはエスケープする必要があるかもしれません。CharacterClass の外で特別な意味を持つ他の文字、例えば *? などは、エスケープする必要はありません。

[編集] POSIXベースの文字クラス

これらの文字クラスは ECMAScript 文法への拡張であり、POSIX 正規表現に見られる文字クラスと等価です。

ClassAtomExClass(C++ only) :

[: ClassName :]

名前付き文字クラス ClassName のメンバーであるすべての文字を表します。この名前は、std::regex_traits::lookup_classname がこの名前に対してゼロ以外を返す場合にのみ有効です。std::regex_traits::lookup_classname で説明されているように、以下の名前は認識されることが保証されています: alnum, alpha, blank, cntrl, digit, graph, lower, print, punct, space, upper, xdigit, d, s, w。追加の名前は、システム提供のロケール(日本語の jdigitjkanji など)によって提供されたり、ユーザー定義の拡張として実装されたりすることがあります。

ClassAtomCollatingElement(C++ only) :

[. ClassName .]

名前付き照合要素を表します。これは単一の文字、または現在のロケール下で単一の単位として照合される文字シーケンス(チェコ語の [.tilde.][.ch.] など)を表すことがあります。この名前は、std::regex_traits::lookup_collatename が空文字列でない場合にのみ有効です。

std::regex_constants::collate を使用する場合、照合要素は常に範囲の端点として使用できます(例:ハンガリー語の [[.dz.]-g])。

ClassAtomEquivalence(C++ only) :

[= ClassName =]

名前付き照合要素と同じ等価クラスのメンバーであるすべての文字、つまり、プライマリ照合キーが照合要素 ClassName のものと同じであるすべての文字を表します。この名前は、その名前に対する std::regex_traits::lookup_collatename が空文字列でなく、かつ std::regex_traits::lookup_collatename の呼び出し結果に対する std::regex_traits::transform_primary が返す値が空文字列でない場合にのみ有効です。

プライマリソートキーとは、大文字小文字、アクセント、またはロケール固有の調整を無視するものです。したがって、例えば [[=a=]] は、a, À, Á, Â, Ã, Ä, Å, A, à, á, â, ã, ä, å のいずれかの文字にマッチします。

ClassName(C++ only) :

ClassNameCharacter
ClassNameCharacter ClassName

ClassNameCharacter(C++ only) :

. = : のいずれでもない SourceCharacter
English 日本語 中文(简体) 中文(繁體)