名稱空間
變體
操作

修改後的 ECMAScript 正則表示式語法

來自 cppreference.com
< cpp‎ | regex

本頁描述了當使用 ECMAScript(預設值)作為 syntax_option_type 構建 std::basic_regex 時所使用的正則表示式語法。有關其他支援的正則表示式語法,請參閱 syntax_option_type

C++ 中的 ECMAScript 3 正則表示式語法是 ECMA-262 語法,其中修改之處在下方標記為 (僅限 C++)

目錄

[編輯] 概述

修改後的正則表示式語法 主要基於 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 指南

[編輯] 備選項

正則表示式模式是一個或多個 Alternative 的序列,它們由析取運算子 | 分隔(換句話說,析取運算子的優先順序最低)。

模式 ::

析取

析取 ::

備選項
備選項 | 析取

模式首先嚐試跳過 Disjunction 並匹配左側的 Alternative,然後匹配正則表示式的其餘部分(在 Disjunction 之後)。

如果失敗,它會嘗試跳過左側的 Alternative 並匹配右側的 Disjunction(後跟正則表示式的其餘部分)。

如果左側的 Alternative、右側的 Disjunction 和正則表示式的其餘部分都有選擇點,那麼在繼續左側 Alternative 中的下一個選擇之前,會嘗試表示式其餘部分中的所有選擇。如果左側 Alternative 中的選擇已用盡,則嘗試右側 Disjunction 而不是左側 Alternative

跳過的 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=[]

[編輯]

每個 Alternative 要麼為空,要麼是 Term 的序列(Term 之間沒有分隔符)

備選項 ::

[空]
備選項

Alternative 總是匹配,並且不消耗任何輸入。

連續的 Term 嘗試同時匹配輸入中連續的部分。

如果左側 Alternative、右側 Term 和正則表示式的其餘部分都有選擇點,那麼在繼續右側 Term 中的下一個選擇之前,會嘗試表示式其餘部分中的所有選擇,並且在繼續左側 Alternative 中的下一個選擇之前,會嘗試右側 Term 中的所有選擇。

#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]

[編輯] 量詞

  • 每個 Term 要麼是一個 Assertion(見下文),要麼是一個 Atom(見下文),要麼是一個緊跟著 QuantifierAtom

 ::

斷言
原子
原子 量詞

每個 Quantifier 要麼是 貪婪 量詞(僅由一個 QuantifierPrefix 組成),要麼是 非貪婪 量詞(由一個 QuantifierPrefix 後面跟一個問號 ? 組成)。

量詞 ::

量詞字首
量詞字首 ?

每個 QuantifierPrefix 確定兩個數字:最小重複次數和最大重複次數,如下所示

量詞字首 最小 最大
* 無窮大
+ 無窮大
?
{ 十進位制數字 } 十進位制數字的值 十進位制數字的值
{ 十進位制數字 , } 十進位制數字的值 無窮大
{ 十進位制數字 , 十進位制數字 } 逗號前的十進位制數字的值 逗號後的十進位制數字的值

單個 DecimalDigits 的值透過對每個數字呼叫 std::regex_traits::value(僅限 C++) 獲得。

緊跟在 Quantifier 後面的 Atom 會按照 Quantifier 指定的次數重複。一個 Quantifier 可以是 非貪婪的,在這種情況下,Atom 模式會盡可能少地重複,同時仍然匹配正則表示式的其餘部分;或者它可以是 貪婪的,在這種情況下,Atom 模式會盡可能多地重複,同時仍然匹配正則表示式的其餘部分。

重複的是 Atom 模式,而不是它匹配的輸入,因此 Atom 的不同重複可以匹配不同的輸入子字串。

如果 Atom 和正則表示式的其餘部分都有選擇點,則 Atom 首先儘可能多地(如果是非貪婪的,則儘可能少地)匹配。在移至 Atom 最後一次重複中的下一個選擇之前,會嘗試正則表示式其餘部分中的所有選擇。在移至 Atom 倒數第二次 (n-1) 次重複中的下一個選擇之前,會嘗試 Atom 最後一次 (n 次) 重複中的所有選擇;此時可能會發現 Atom 的重複次數可以更多或更少;這些重複(再次,從儘可能少或儘可能多開始)在移至 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=[]

[編輯] 斷言

斷言 匹配條件,而不是輸入字串的子字串。它們從不消耗輸入中的任何字元。每個 斷言 都是以下之一

斷言 ::

^
$
\ b
\ B
( ? = 析取 )
( ? ! 析取 )

斷言 ^(行首)匹配

1) 緊跟在 LineTerminator 字元之後的位置 (可能不支援)(直到 C++17)(僅當啟用 std::regex_constants::multiline(僅限 C++) 時才保證)(自 C++17 起)
2) 輸入的開頭(除非啟用 std::regex_constants::match_not_bol(僅限 C++)

斷言 $(行尾)匹配

1) LineTerminator 字元的位置 (可能不支援)(直到 C++17)(僅當啟用 std::regex_constants::multiline(僅限 C++) 時才保證)(自 C++17 起)
2) 輸入的結尾(除非啟用 std::regex_constants::match_not_eol(僅限 C++)

在上述兩個斷言和下面的 Atom . 中,LineTerminator 是以下四個字元之一:U+000A\n 或換行)、U+000D\r 或回車)、U+2028(行分隔符)或 U+2029(段落分隔符)

斷言 \b(單詞邊界)匹配

1) 單詞的開頭(當前字元是字母、數字或下劃線,且前一個字元不是)
2) 單詞的結尾(當前字元不是字母、數字或下劃線,且前一個字元是其中之一)
3) 如果第一個字元是字母、數字或下劃線,則為輸入的開頭(除非啟用 std::regex_constants::match_not_bow(僅限 C++)
4) 如果最後一個字元是字母、數字或下劃線,則為輸入的結尾(除非啟用 std::regex_constants::match_not_eow(僅限 C++)

斷言 \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=[]

[編輯] 原子

一個 Atom 可以是以下之一

原子 ::

模式字元
.
\ 原子轉義
字元類
( 析取 )
( ? : 析取 )

其中 AtomEscape

十進位制轉義
字元轉義
字元類轉義

不同型別的原子求值方式不同。

[編輯] 子表示式

Atom ( Disjunction ) 是一個標記的子表示式:它執行 Disjunction 並將 Disjunction 消耗的輸入子字串的副本儲存在子匹配陣列中,其索引對應於在整個正則表示式中此刻遇到的標記子表示式的左括號 ( 的次數。

除了在 std::match_results 中返回之外,捕獲的子匹配還可以作為反向引用(\1\2 等)進行訪問,並在正則表示式中引用。請注意,std::regex_replace 使用 $ 代替 \ 來表示反向引用($1$2 等),其方式與 String.prototype.replace (ECMA-262, 第 15.5.4.11 部分) 相同。

Atom ( ? : Disjunction )(非標記子表示式)只評估 Disjunction,而不將其結果儲存在子匹配中。這純粹是一個詞法分組。

[編輯] 反向引用

十進位制轉義 ::

DecimalIntegerLiteral [lookaheadDecimalDigit]

如果 \ 後跟一個十進位制數 N,且其第一位不是 0,則該轉義序列被視為 反向引用。值 N 透過對每個數字呼叫 std::regex_traits::value(僅限 C++) 並使用十進位制算術組合其結果獲得。如果 N 大於整個正則表示式中左捕獲括號的總數,則為錯誤。

當反向引用 \N 作為 Atom 出現時,它匹配與當前儲存在子匹配陣列的第 N 個元素中的子字串相同的子字串。

十進位制轉義 \0 不是反向引用:它是一個字元轉義,表示 NUL 字元。它後面不能跟十進位制數字。

如上所述,請注意 std::regex_replace 使用 $ 代替 \ 來表示反向引用($1$2 等)。

[編輯] 單字元匹配

Atom . 匹配並消耗輸入字串中的任何一個字元,除了 LineTerminatorU+000DU+000AU+2029U+2028

Atom PatternCharacter,其中 PatternCharacter 是除字元 ^ $ \ . * + ? ( ) [ ] { } | 之外的任何 SourceCharacter,如果它等於此 PatternCharacter,則匹配並消耗輸入中的一個字元。

此和所有其他單字元匹配的相等性定義如下

1) 如果設定了 std::regex_constants::icase,則如果 std::regex_traits::translate_nocase 的返回值相等,則字元相等 (僅限 C++)
2) 否則,如果設定了 std::regex_constants::collate,則如果 std::regex_traits::translate 的返回值相等,則字元相等 (僅限 C++)
3) 否則,如果 operator== 返回 true,則字元相等。

每個由跳脫字元 \ 後跟 CharacterEscape 組成的 Atom,以及特殊 DecimalEscape \0,如果它等於 CharacterEscape 所表示的字元,則匹配並消耗輸入中的一個字元。識別以下字元轉義序列

字元轉義 ::

控制轉義
c 控制字母
十六進位制轉義序列
Unicode轉義序列
標識轉義

在這裡,ControlEscape 是以下五個字元之一:f n r t v

控制轉義 程式碼單元 名稱
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 後跟正好兩個 HexDigit(其中 HexDigit0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F 之一)。此字元轉義匹配其程式碼單元等於兩位十六進位制數的數字值的字元。

UnicodeEscapeSequence 是字母 u 後跟正好四個 HexDigit。此字元轉義匹配其程式碼單元等於此四位十六進位制數的數字值的字元。如果該值不適合 std::basic_regexCharT,則會丟擲 std::regex_error (僅限 C++)

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

[編輯] 字元類

原子可以表示一個字元類,也就是說,如果它屬於預定義字元組之一,它將匹配並消耗一個字元。

字元類可以透過字元類轉義符引入

原子 ::

\ 字元類轉義

或者直接

原子 ::

字元類

字元類轉義是某些常見字元類的簡寫,如下所示

字元類轉義 類名錶達式(僅限 C++) 含義
d [[:digit:]] 數字
D [^[:digit:]] 非數字
s [[:space:]] 空白字元
S [^[:space:]] 非空白字元
w [_[:alnum:]] 字母數字字元和字元 _
W [^_[:alnum:]] 除字母數字或 _ 之外的字元
C++ 中這些字元類轉義符的精確含義是根據依賴於區域設定的命名字元類定義的,而不是像 ECMAScript 中那樣透過顯式列出可接受的字元來定義的。

CharacterClass 是一個用方括號括起來的 ClassRanges 序列,可選地以否定運算子 ^ 開頭。如果以 ^ 開頭,則此 Atom 匹配任何不屬於所有 ClassRanges 的並集所表示的字元集的字元。否則,此 Atom 匹配任何屬於所有 ClassRanges 的並集所表示的字元集的字元。

字元類 ::

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

ClassRanges:

[空]
NonemptyClassRanges

NonemptyClassRanges ::

ClassAtom
ClassAtom NonemptyClassRangesNoDash
ClassAtom - ClassAtom ClassRanges

如果非空類範圍的形式為 ClassAtom - ClassAtom,它匹配由以下方式定義的範圍內的任何字元:(僅限 C++)

第一個 ClassAtom 必須匹配單個排序元素 c1,第二個 ClassAtom 必須匹配單個排序元素 c2。為了測試輸入字元 c 是否由該範圍匹配,執行以下步驟

1) 如果 std::regex_constants::collate 未設定,則透過比較碼點直接匹配字元:如果 c1 <= c && c <= c2,則匹配 c
1) 否則(如果 std::regex_constants::collate 已啟用)
1) 如果 std::regex_constants::icase 已啟用,則所有三個字元(cc1c2)都傳遞給 std::regex_traits::translate_nocase
2) 否則(如果 std::regex_constants::icase 未設定),則所有三個字元(cc1c2)都傳遞給 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++)
ClassAtomCollatingElement(僅限 C++)
ClassAtomEquivalence(僅限 C++)

ClassAtomNoDash:

SourceCharacter 但不是 \ 或 ] 或 - 之一
\ 類轉義

每個 ClassAtomNoDash 表示一個單一字元——要麼是原樣的 SourceCharacter,要麼按如下方式轉義

ClassEscape:

十進位制轉義
b
字元轉義
字元類轉義

特殊 ClassEscape \b 產生一個字元集,它匹配程式碼單元 U+0008(退格符)。在 CharacterClass 之外,它是單詞邊界 Assertion

CharacterClass 內使用 \B 和使用任何反向引用(非零的 DecimalEscape)都是錯誤。

在某些情況下,字元 -] 可能需要轉義才能被視為原子。在 CharacterClass 之外具有特殊含義的其他字元,例如 *?,則不需要轉義。

[編輯] 基於 POSIX 的字元類

這些字元類是對 ECMAScript 語法的擴充套件,並且等同於 POSIX 正則表示式中發現的字元類。

ClassAtomExClass(僅限 C++)

[: 類名 :]

表示屬於命名字元類 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++)

[. 類名 .]

表示命名的排序元素,它可能代表一個單一字元或在給定區域設定下作為一個單元進行排序的字元序列,例如捷克語中的 [.tilde.][.ch.]。僅當 std::regex_traits::lookup_collatename 返回非空字串時,該名稱才有效。

使用 std::regex_constants::collate 時,排序元素始終可以用作範圍的終點(例如匈牙利語中的 [[.dz.]-g])。

ClassAtomEquivalence(僅限 C++)

[= 類名 =]

表示與命名排序元素屬於同一等價類的所有字元,即,所有主要排序鍵與排序元素 ClassName 相同的字元。僅當 std::regex_traits::lookup_collatename 對於該名稱返回非空字串,並且對 std::regex_traits::lookup_collatename 的呼叫結果的 std::regex_traits::transform_primary 返回值非空時,該名稱才有效。

主排序鍵忽略大小寫、重音或區域特定調整;因此例如 [[=a=]] 匹配以下任何字元:a, À, Á, Â, Ã, Ä, Å, A, à, á, â, ã, ä 和 å。

類名(僅限 C++)

類名字元
類名字元 類名

類名字元(僅限 C++)

SourceCharacter 但不是 . = : 之一