命名空間
變體
動作

修改過的 ECMAScript 正規表示式語法

出自 cppreference.com
< cpp‎ | regex

本頁面描述當 std::basic_regex 建構時將 syntax_option_type 設定為 ECMAScript(預設值)時所使用的正規表示式語法。請參閱 syntax_option_type 以了解其他支援的正規表示式語法。

C++ 中的 ECMAScript 3 正規表示式語法是 ECMA-262 語法,並加上下方以 (僅限 C++) 標記的修改。

目錄

[編輯] 概覽

修改後的正規表示式語法主要為 ECMAScript RegExp 語法,並在 ClassAtom 下針對地區設定 (locale) 進行了類似 POSIX 的擴充。針對相等性檢查與數字解析做了一些釐清。對於此處的許多範例,您可以在瀏覽器控制台中嘗試等效的語法。

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

標準中的「規範性參考」指定了 ECMAScript 3。我們在此連結到 ECMAScript 5.1 規範,因為該版本與 ECMAScript 3 僅有微小差異,且提供 HTML 版本。關於該語法的特性概覽,請參閱 MDN JavaScript RegExp 指南

[編輯] 選擇 (Alternatives)

正規表示式模式是由一個或多個「選擇」(Alternative) 組成的序列,並由析取運算子 | 分隔(換句話說,析取運算子的優先權最低)。

模式 (Pattern) ::

析取 (Disjunction)

析取 (Disjunction) ::

選擇 (Alternative)
Alternative | Disjunction

該模式首先嘗試跳過 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=[]

[編輯] 項 (Terms)

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

選擇 (Alternative) ::

[空]
Alternative 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]

[編輯] 量詞 (Quantifiers)

  • 每個 Term 要麼是 Assertion(斷言,見下文),要麼是 Atom(原子,見下文),或者是緊跟量詞的 Atom

項 (Term) ::

斷言 (Assertion)
原子 (Atom)
Atom Quantifier

每個 Quantifier 要麼是「貪婪」(greedy) 量詞(僅包含一個 QuantifierPrefix),要麼是「非貪婪」(non-greedy) 量詞(包含一個 QuantifierPrefix 後接問號 ?)。

量詞 (Quantifier) ::

量詞前綴 (QuantifierPrefix)
QuantifierPrefix ?

每個 QuantifierPrefix 決定兩個數字:重複的最小次數與最大次數,如下所示:

量詞前綴 (QuantifierPrefix) 最小值 最大值
* infinity
+ infinity
?
{ DecimalDigits } DecimalDigits 的值 DecimalDigits 的值
{ DecimalDigits , } DecimalDigits 的值 infinity
{ DecimalDigits , DecimalDigits } 逗號前 DecimalDigits 的值 逗號後 DecimalDigits 的值

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

後接 QuantifierAtom 會重複 Quantifier 指定的次數。Quantifier 可以是「非貪婪」的,此時 Atom 模式會在仍能匹配正規表示式其餘部分的前提下,重複盡可能少的次數;也可以是「貪婪」的,此時 Atom 模式會在仍能匹配正規表示式其餘部分的前提下,重複盡可能多的次數。

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

如果 Atom 和正規表示式的其餘部分皆有選擇點,則 Atom 會首先盡可能多次(或少次,若為「非貪婪」)地進行匹配。在進入 Atom 最後一次重複中的下一個選擇之前,會先嘗試正規表示式其餘部分的所有選擇。在進入 Atom 倒數第二次 (n-1) 重複中的下一個選擇之前,會先嘗試 Atom 最後一次 (nth) 重複的所有選擇;此時可能發現 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=[]

[編輯] 斷言 (Assertions)

Assertion 匹配條件而非輸入字串的子字串。它們從不消耗輸入中的任何字元。每個 Assertion 為下列之一:

斷言 (Assertion) ::

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

斷言 ^(行首)匹配:

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=[]

[編輯] 原子 (Atoms)

Atom 可以是以下之一:

原子 (Atom) ::

PatternCharacter(模式字元)
.
\ AtomEscape
CharacterClass(字元類別)
( Disjunction )
( ? : Disjunction )

其中 AtomEscape 為:

DecimalEscape(十進位逸出)
CharacterEscape(字元逸出)
CharacterClassEscape(字元類別逸出)

不同類型的原子有不同的計算方式。

[編輯] 子表示式 (Sub-expressions)

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,且不會將其結果存入子匹配中。這僅用於純詞法分組。

[編輯] 反向參考 (Backreferences)

DecimalEscape(十進位逸出) ::

DecimalIntegerLiteral [lookaheadDecimalDigit]

如果 \ 後跟一個十進位數字 N,且其第一個數字不是 0,則該逸出序列被視為「反向參考」。值 N 是透過對每個數字呼叫 std::regex_traits::value(僅限 C++) 並以十進位運算合併結果獲得的。如果 N 大於整個正規表示式中左捕獲括號的總數,則為錯誤。

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

十進位逸出 \0 並非反向參考:它是一個表示 NUL 字元的字元逸出。它後面不能跟隨十進位數字。

如上所述,請注意 std::regex_replace 使用 $ 而非 \ 進行反向參考(如 $1, $2, ...)。

[編輯] 單字元匹配

Atom . 匹配並消耗輸入字串中的任意一個字元(除 LineTerminator (U+000D, U+000A, U+2029, 或 U+2028) 外)。

Atom PatternCharacter(其中 PatternCharacter 是除 ^ $ \ . * + ? ( ) [ ] { } | 之外的任何 SourceCharacter)在相等時匹配並消耗輸入中的一個字元。

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

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,以及特殊的十進位逸出 \0,在等於 CharacterEscape 所表示的字元時匹配並消耗一個輸入字元。支援以下字元逸出序列:

CharacterEscape(字元逸出) ::

ControlEscape(控制逸出)
c ControlLetter(控制字母)
HexEscapeSequence(十六進位逸出序列)
UnicodeEscapeSequence(Unicode 逸出序列)
IdentityEscape(標識逸出)

其中 ControlEscape 為以下五個字元之一:f n r t v

ControlEscape(控制逸出) 代碼單元 名稱
f U+000C 換頁符 (form feed)
n U+000A 換行符 (new line)
r U+000D 回車符 (carriage return)
t U+0009 水平定位符 (horizontal tab)
v U+000B 垂直定位符 (vertical tab)

ControlLetter 是任何大小寫 ASCII 字母。此字元逸出匹配代碼單元等於 ControlLetter 的代碼單元除以 32 的餘數的字元。例如,\cD\cd 皆匹配代碼單元 U+0004 (EOT),因為 'D' 為 U+00440x44 % 32 == 4;而 'd' 為 U+00640x64 % 32 == 4

HexEscapeSequence 為字母 x 後接恰好兩個 HexDigit(十六進位數字,為 0 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

[編輯] 字元類別 (Character classes)

原子可以表示字元類別,即若字元屬於預定義的字元組之一,它就會匹配並消耗一個字元。

字元類別可以透過字元類別逸出引入:

原子 (Atom) ::

\ CharacterClassEscape

或直接使用:

原子 (Atom) ::

CharacterClass(字元類別)

字元類別逸出是一些常見字元類別的簡寫,如下所示:

CharacterClassEscape(字元類別逸出) 類別名稱表示式(僅限 C++) 含義
d [[:digit:]] digits
D [^[:digit:]] 非數字
s [[:space:]] 空白字元
S [^[:space:]] 非空白字元
w [_[:alnum:]] 字母數字字元以及字元 _
W [^_[:alnum:]] 除字母數字或 _ 以外的字元
C++ 中這些字元類別逸出的確切含義是根據地區相關的具名字元類別定義的,而不是像 ECMAScript 那樣明確列出可接受的字元。

CharacterClass 是括號括住的 ClassRanges 序列,可選地以否定運算子 ^ 開頭。若以 ^ 開頭,則此 Atom 匹配任何「不」在所有 ClassRanges 聯集所表示之字元集合內的字元。否則,此 Atom 匹配任何「在」該集合內的字元。

CharacterClass(字元類別) ::

[ [ 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,則所有三個字元 (c, c1, c2) 都會傳遞給 std::regex_traits::translate_nocase
2) 否則(若未設定 std::regex_constants::icase),所有三個字元 (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++)
ClassAtomCollatingElement(僅限 C++)
ClassAtomEquivalence(僅限 C++)

ClassAtomNoDash:

\]- 之外的 SourceCharacter
\ ClassEscape

每個 ClassAtomNoDash 表示一個單一字元——即原樣的 SourceCharacter 或如下逸出:

ClassEscape:

DecimalEscape(十進位逸出)
b
CharacterEscape(字元逸出)
CharacterClassEscape(字元類別逸出)

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

CharacterClass 內部使用 \B 或任何反向參考(非零的 DecimalEscape)是錯誤的。

在某些情況下,字元 -] 可能需要逸出才能被視為原子。其他在 CharacterClass 外有特殊意義的字元(如 *?)則不需要逸出。

[編輯] 基於 POSIX 的字元類別

這些字元類別是對 ECMAScript 語法的擴充,等同於 POSIX 正規表示式中的字元類別。

ClassAtomExClass(僅限 C++)

[: 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++)

[. ClassName .]

表示命名排序元素,其可代表單一字元或在嵌入地區下作為單一單元排序的字元序列,例如捷克語中的 [.tilde.][.ch.]。名稱僅在 std::regex_traits::lookup_collatename 不為空字串時有效。

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

ClassAtomEquivalence(僅限 C++)

[= ClassName =]

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

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

ClassName(僅限 C++)

ClassNameCharacter
ClassNameCharacter ClassName

ClassNameCharacter(僅限 C++)

. = : 之外的 SourceCharacter
English Deutsch 日本語 中文(简体) 中文(繁體)