Modified ECMAScript regular expression grammar
本页描述了当
std::basic_regex
构造时
syntax_option_type
设置为
ECMAScript
(默认值)时所使用的正则表达式语法。关于其他支持的正则表达式语法,请参阅
syntax_option_type
。
C++ 中的
ECMAScript
3 正则表达式语法基于
ECMA-262 语法
,并包含下方标有
(C++ only)
的修改项。
目录 |
概述
修改后的 正则表达式语法 主要基于ECMAScript正则表达式语法,并在 ClassAtom 下对区域设置进行了POSIX风格的扩展。同时明确了相等性检查和数字解析的规则。对于本文中的许多示例,您可以在浏览器控制台中尝试以下等效代码:
function match(s, re) { return s.match(new RegExp(re)); }
标准中的“规范性引用”指定了ECMAScript 3。我们在此链接到ECMAScript 5.1规范,因为这是与ECMAScript 3仅有细微差异的版本,并且提供了HTML版本。有关该方言特性的概述,请参阅 MDN关于JavaScript正则表达式的指南 。
替代方案
正则表达式模式是由一个或多个
候选项
组成的序列,这些候选项通过析取运算符
|
分隔(换言之,析取运算符具有最低优先级)。
模式 ::
- 析取
析取 ::
- 替代方案
-
替代方案
|析取
该模式首先尝试跳过 析取 并匹配左侧的 备选项 ,然后匹配正则表达式的剩余部分(析取之后的内容)。
如果失败,它会尝试跳过左侧的 Alternative 并匹配右侧的 Disjunction (后跟正则表达式的其余部分)。
如果左侧 Alternative 、右侧 Disjunction 以及正则表达式剩余部分均包含选择点,则会在转向左侧 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"); // 左侧候选项首先匹配 // 输入与左侧候选项(a)匹配后,继续匹配正则表达式的剩余部分(c|bc)成功 // 导致 m[1]="a" 和 m[4]="bc" // 被跳过的候选项(ab)和(c)使其子匹配 m[3] 和 m[5] 为空 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 会尝试同时匹配输入中的连续部分。
如果左侧 备选项 、右侧 术语项 以及正则表达式剩余部分均存在选择点,系统会先尝试表达式剩余部分的所有选择,再转向右侧 术语项 的下一个选择,而右侧 术语项 的所有选择尝试完毕后,才会转向左侧 备选项 的下一个选择。
#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 << "]: 无匹配\n"; } int main() { show_matches("abcdef", ""); // 空正则表达式是单个空候选项 show_matches("abc", "abc|"); // 左侧候选项首先匹配 show_matches("abc", "|abc"); // 左侧候选项首先匹配,使 abc 未被匹配 }
输出:
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 (见下文),要么是一个 Atom 后紧跟一个 Quantifier
术语 ::
- 断言
- 原子
- 原子 量词
每个
量词
要么是
贪婪
量词(仅包含一个
量词前缀
),要么是
非贪婪
量词(包含一个
量词前缀
后接问号
?
)。
量词 ::
- 量词前缀
-
量词前缀
?
每个 QuantifierPrefix 会确定两个数值:最小重复次数和最大重复次数,具体对应关系如下:
| 量词前缀 | 最小值 | 最大值 |
|---|---|---|
*
|
零 | 无穷大 |
+
|
一 | 无穷大 |
?
|
零 | 一 |
{
DecimalDigits
}
|
DecimalDigits的值 | DecimalDigits的值 |
{
DecimalDigits
,
}
|
DecimalDigits的值 | 无穷大 |
{
DecimalDigits
,
DecimalDigits
}
|
逗号前的DecimalDigits值 | 逗号后的DecimalDigits值 |
各个 DecimalDigits 的值是通过对每个数字调用 std::regex_traits::value (仅限C++) 获得的。
一个 原子 后接一个 量词 时,该原子会按照量词指定的次数重复匹配。量词可以是 非贪婪模式 ——此时原子模式会以最少重复次数仍能匹配正则表达式剩余部分的方式执行;也可以是 贪婪模式 ——此时原子模式会以最多重复次数仍能匹配正则表达式剩余部分的方式执行。
Atom 模式是被重复的部分,而非其匹配的输入内容,因此不同的 Atom 重复可以匹配不同的输入子字符串。
如果 Atom 和正则表达式剩余部分均存在选择点,首先将 Atom 匹配尽可能多(若为 非贪婪模式 则尽可能少)的次数。在转向 Atom 最后一次重复中的下一个选择之前,会先尝试正则表达式剩余部分的所有选择。在转向倒数第二次(n–1次) Atom 重复中的下一个选择之前,会先尝试最后一次(第n次) Atom 重复中的所有选择;此时可能会发现现在可以匹配更多或更少的 Atom 重复次数;这些可能性将被全部尝试(再次从尽可能少或尽可能多开始),然后才会转向倒数第二次(n-1次) Atom 重复中的下一个选择,依此类推。
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 << "]: 无匹配\n"; } int main() { // 贪婪匹配,重复 [a-z] 4 次 show_matches("abcdefghi", "a[a-z]{2,4}"); // 非贪婪匹配,重复 [a-z] 2 次 show_matches("abcdefghi", "a[a-z]{2,4}?"); // 量词的选择点排序导致匹配结果包含两次重复: // 第一次匹配子串 "aa",第二次匹配子串 "ba", // 留下 "ac" 未匹配("ba" 出现在捕获组 m[1] 中) show_matches("aabaac", "(aa|aabaac|ba|b|c)*"); // 量词的选择点排序使此正则表达式计算 10 和 15 的最大公约数 //(结果为 5,并在 m[1] 中填充 "aaaaa") show_matches("aaaaaaaaaa,aaaaaaaaaaaaaaa", "^(a+)\\1*,\\1+$"); // 子串 "bbb" 未出现在捕获组 m[4] 中, // 因为当原子 (a+)?(b+)?(c) 的第二次重复匹配子串 "ac" 时,该组被清空 // 注意:gcc 对此处理有误 - 未按 ECMA-262 21.2.2.5.1 要求正确清空 // matches[4] 捕获组,因此错误地捕获了 "bbb" 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 -
(?=析取表达式) -
(?!析取表达式)
断言
^
(行首) 匹配
断言
$
(行尾)匹配
在上述两个断言以及下面的原子符号
.
中,
LineTerminator
是以下四个字符之一:
U+000A
(
\n
或换行符)、
U+000D
(
\r
或回车符)、
U+2028
(行分隔符)或
U+2029
(段落分隔符)
断言
\b
(单词边界)匹配
断言
\B
(负向单词边界)匹配除以下情况外的所有内容
断言
(
?
=
Disjunction
)
(零宽度正向先行断言)在当前输入位置匹配的条件是:
Disjunction
能够在此位置匹配
断言
(
?
!
Disjunction
)
(零宽度负向先行断言)在当前输入位置处,当
Disjunction
无法匹配时成功匹配。
对于两种向前查找断言,当匹配 Disjunction 时,在匹配正则表达式剩余部分之前不会前进匹配位置。此外,如果 Disjunction 在当前位置存在多种匹配方式,仅会尝试第一种匹配方式。
ECMAScript 禁止回溯到前视析取中,这会影响从正则表达式剩余部分反向引用到正向先行断言的行为(参见下方示例)。从正则表达式其余部分反向引用到负向先行断言的结果始终未定义(因为前视析取必须失败才能继续执行)。
注意:前视断言可用于在多个正则表达式之间创建逻辑与关系(参见下方示例)。
#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() { // 匹配输入末尾的 a show_matches("aaa", "a$"); // 匹配第一个单词末尾的 o show_matches("moo goo gai pan", "o\\b"); // 正向先行断言在第一个 b 之后立即匹配空字符串 // 虽然 m[0] 为空,但 m[1] 被填充为 "aaa" show_matches("baaabac", "(?=(a+))"); // 由于禁止回溯到正向先行断言中, // 此处匹配 aba 而非 aaaba show_matches("baaabac", "(?=(a+))a*b\\1"); // 通过正向先行断言实现逻辑与:此密码需满足以下条件才匹配 // 至少包含一个小写字母 // 且至少包含一个大写字母 // 且至少包含一个标点符号 // 且长度至少为 6 个字符 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=[]
原子
一个 原子 可以是以下类型之一:
原子 ::
- 模式字符
-
. -
\原子转义 - 字符类
-
(析取) -
(?:析取)
其中 AtomEscape ::
- DecimalEscape
- CharacterEscape
- CharacterClassEscape
不同种类的原子具有不同的求值方式。
子表达式
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
进行求值,且不会将其结果存储到子匹配中。这是一种纯粹的词法分组。
|
本节内容不完整
原因:缺少示例 |
反向引用
DecimalEscape ::
- DecimalIntegerLiteral [ lookahead ∉ DecimalDigit ]
如果
\
后跟一个首位非
0
的十进制数字
N
,则该转义序列被视为
反向引用
。数值
N
通过对每个数字调用
std::regex_traits::value
(仅限 C++)
并采用十进制算术组合其结果而获得。若
N
大于整个正则表达式中左捕获括号的总数,则视为错误。
当反向引用
\N
作为
原子
出现时,它会匹配当前存储在子匹配数组第 N 个元素中的相同子字符串。
十进制转义符
\0
并非反向引用:它是一个表示
NUL
字符的字符转义符。其后不能紧跟十进制数字。
如前所述,请注意
std::regex_replace
使用
$
而非
\
作为反向引用标识符(
$1
、
$2
等)。
|
本节内容不完整
原因:缺少示例 |
单字符匹配
Atom
.
匹配并消耗输入字符串中除
行终止符
(
U+000D
、
U+000A
、
U+2029
或
U+2028
)之外的任意单个字符
除了字符
^ $ \ . * + ? ( ) [ ] { } |
之外的任何
源字符
所构成的
原子模式字符
,若输入字符与该
模式字符
相等,则匹配并消耗输入中的一个字符。
该字符及所有其他单字符匹配的相等性定义如下:
每个由转义字符
\
后接
CharacterEscape
组成的
Atom
,以及特殊的十进制转义序列
\0
,当输入字符与
CharacterEscape
所表示的字符相等时,将匹配并消耗输入中的一个字符。可识别的字符转义序列包括:
CharacterEscape ::
- ControlEscape
-
cControlLetter - HexEscapeSequence
- UnicodeEscapeSequence
- IdentityEscape
这里,
ControlEscape
是以下五个字符之一:
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+0044
且
0x44
%
32
==
4
,而 'd' 对应
U+0064
且
0x64
%
32
==
4
。
HexEscapeSequence
是字母
x
后跟恰好两个
HexDigit
(其中
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_regex
的
CharT
类型,将抛出
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() { // 大多数转义字符与C++类似,除了元字符。对于斜杠,您需要双重转义或使用原始字符串。 show_matches(L"C++\\", LR"(C\+\+\\)"); // 转义序列与NUL字符。 std::wstring s(L"ab\xff\0cd", 5); show_matches(s, L"(\\0|\\u00ff)"); // 未定义非BMP Unicode的匹配,因为ECMAScript使用UTF-16原子。 // 这个表情符号香蕉是否匹配可能依赖于平台: // 这些需要使用宽字符串! 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
字符类
一个Atom可以表示一个字符类,即当字符属于预定义字符组之一时,它将匹配并消耗一个字符。
字符类可以通过字符类转义引入:
原子 ::
-
\字符类转义
或直接
原子 ::
- 字符类
字符类转义是某些常见字符类的简写形式,具体如下:
| 字符类转义 | 类名表达式 (仅限C++) | 含义 |
|---|---|---|
d
|
[[:digit:]]
|
数字字符 |
D
|
[^[:digit:]]
|
非数字字符 |
s
|
[[:space:]]
|
空白字符 |
S
|
[^[:space:]]
|
非空白字符 |
w
|
[_[:alnum:]]
|
字母数字字符及字符
_
|
W
|
[^_[:alnum:]]
|
除字母数字和
_
外的字符
|
一个
字符类
是由括号包围的
类范围
序列,可选择以取反运算符
^
开头。若以
^
起始,该
原子
将匹配任何不属于所有
类范围
并集所表示字符集合的字符。否则,该
原子
将匹配任何属于所有
类范围
并集所表示字符集合中的字符。
CharacterClass ::
-
[[前瞻字符 ∉ {^} 字符类范围] -
[^字符类范围]
类范围 ::
- [空]
- 非空类范围
非空类范围 ::
- 类原子
- 类原子 非空类范围无连字符
- 类原子 - 类原子 类范围
如果非空字符类范围具有形式
ClassAtom
-
ClassAtom
,它将匹配按如下方式定义的字符范围:
(仅限 C++)
第一个
ClassAtom
必须匹配单个对照元素
c1
,第二个
ClassAtom
必须匹配单个对照元素
c2
。要测试输入字符
c
是否被此范围匹配,需执行以下步骤:
transformed c1 <= transformed c && transformed c <= transformed c2
条件时,字符
c
即匹配成功
字符
-
在以下情况下会被按字面意义处理:
- ClassRanges 的首个或末尾字符
- 短横线分隔范围规范的起始或结束 ClassAtom
- 紧跟在短横线分隔范围规范之后
- 使用反斜杠作为 CharacterEscape 进行转义
非空类范围无破折号 ::
- 类原子
- 无连字符类原子 非空无连字符类范围
- 无连字符类原子 - 类原子 类范围
ClassAtom ::
-
- - ClassAtomNoDash
- ClassAtomExClass (仅限 C++)
- ClassAtomCollatingElement (仅限 C++)
- ClassAtomEquivalence (仅限 C++)
ClassAtomNoDash ::
-
SourceCharacter
但不包括
\ 或 ] 或 - -
\ClassEscape
每个 ClassAtomNoDash 代表单个字符——可以是原样的 SourceCharacter ,或按如下方式转义:
类转义 ::
- 十进制转义
-
b - 字符转义
- 字符类转义
特殊的
ClassEscape
\b
生成匹配代码单元 U+0008(退格符)的字符集。在
CharacterClass
外部,它是单词边界
Assertion
。
在字符类中使用
\B
以及使用任何反向引用(除零之外的十进制转义)都是错误的。
字符
-
和
]
在某些情况下可能需要转义才能被视为原子。在
字符类
外具有特殊含义的其他字符(例如
*
或
?
)则无需转义。
|
本节内容不完整
原因:缺少示例 |
基于POSIX的字符类
这些字符类是ECMAScript语法的扩展,与POSIX正则表达式中的字符类等效。
ClassAtomExClass (C++ only) ::
-
[:类名:]
表示属于命名字符类
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
。系统提供的区域设置(如日语中的
jdigit
或
jkanji
)可能提供其他名称,或通过用户自定义扩展实现。
ClassAtomCollatingElement (C++ only) ::
-
[.类名.]
表示命名的排序元素,该元素可能代表单个字符或在当前语言环境下作为单个单元进行排序的字符序列,例如捷克语中的
[.tilde.]
或
[.ch.]
。仅当
std::regex_traits::lookup_collatename
返回非空字符串时,该名称才有效。
当使用
std::regex_constants::collate
时,排序元素始终可用作范围的端点(例如匈牙利语中的
[[.dz.]-g]
)。
类原子等价性 (仅限C++) ::
-
[=类名=]
表示与指定排序元素属于同一等价类的所有字符,即所有主排序键与排序元素 ClassName 相同的字符。该名称仅在以下情况下有效: std::regex_traits::lookup_collatename 对该名称的调用返回非空字符串,且通过 std::regex_traits::transform_primary 对 std::regex_traits::lookup_collatename 调用结果进行转换后的返回值也为非空字符串。
主排序键是一种忽略大小写、重音符号或区域特定定制化的键;例如
[[=a=]]
会匹配以下任意字符:
a, À, Á, Â, Ã, Ä, Å, A, à, á, â, ã, ä and å。
类名 (仅限C++) ::
- 类名字符
- 类名字符 类名
类名字符 (仅限C++) ::
-
SourceCharacter
但不包括
. = :中的字符
|
本节内容不完整
原因:缺少示例 |