Изменённая грамматика регулярных выражений ECMAScript
На этой странице описана грамматика регулярных выражений, используемая при создании std::basic_regex, если для syntax_option_type задано значение ECMAScript (по умолчанию). Другие поддерживаемые грамматики регулярных выражений см. в разделе syntax_option_type.
Грамматика регулярных выражений ECMAScript 3 в C++ — это грамматика ECMA-262 с изменениями, отмеченными ниже пометкой (только C++).
Обзор
Изменённая грамматика регулярных выражений в основном представляет собой грамматику RegExp ECMAScript с расширением типа POSIX для локалей в разделе ClassAtom. Внесены некоторые уточнения, касающиеся проверок равенства и разбора чисел. Многие приведённые здесь примеры можно проверить в консоли браузера с помощью эквивалентного выражения:
function match(s, re) { return s.match(new RegExp(re)); }
«Нормативные ссылки» в стандарте указывают на ECMAScript 3. Здесь приведена ссылка на спецификацию ECMAScript 5.1, поскольку эта версия отличается от ECMAScript 3 лишь незначительно и доступна в формате HTML. Обзор возможностей диалекта см. в руководстве MDN по RegExp в JavaScript.
Альтернативы
Шаблон регулярного выражения представляет собой одну или несколько Alternative, разделённых оператором дизъюнкции | (иначе говоря, оператор дизъюнкции имеет наименьший приоритет).
Pattern ::
DisjunctionDisjunction ::
- Alternative
-
Alternative
|Disjunction
Сначала шаблон пытается пропустить Disjunction и сопоставить левую Alternative, а затем оставшуюся часть регулярного выражения (после дизъюнкции).
Если это не удаётся, он пытается пропустить левую 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"); // 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 ::
- [empty]
- 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]
Квантификаторы
- Каждый Term — это либо Assertion (см. ниже), либо Atom (см. ниже), либо Atom, за которым непосредственно следует Quantifier
Term ::
- Assertion
- Atom
- Atom Quantifier
Каждый Quantifier является либо жадным квантификатором (состоящим только из одного QuantifierPrefix), либо ленивым квантификатором (состоящим из одного QuantifierPrefix, за которым следует вопросительный знак ?).
Quantifier ::
- QuantifierPrefix
-
QuantifierPrefix
?
Каждый QuantifierPrefix задаёт два числа: минимальное и максимальное количество повторений, как показано ниже:
| QuantifierPrefix | Минимум | Максимум |
|---|---|---|
* | ноль | бесконечность |
+ | один | бесконечность |
? | ноль | один |
{ DecimalDigits } | значение DecimalDigits | значение DecimalDigits |
{ DecimalDigits , } | значение DecimalDigits | бесконечность |
{ DecimalDigits , DecimalDigits } | значение DecimalDigits перед запятой | значение DecimalDigits после запятой |
Значения отдельных DecimalDigits получают вызовом std::regex_traits::value(только C++) для каждой цифры.
Atom, за которым следует Quantifier, повторяется указанное в Quantifier число раз. Quantifier может быть ленивым: в этом случае шаблон Atom повторяется как можно меньше раз, но так, чтобы оставшаяся часть регулярного выражения всё ещё сопоставлялась. Либо он может быть жадным: в этом случае шаблон Atom повторяется как можно больше раз, но так, чтобы оставшаяся часть регулярного выражения всё ещё сопоставлялась.
Повторяется шаблон Atom, а не соответствующие ему входные данные, поэтому разные повторения Atom могут сопоставляться с разными подстроками входных данных.
Если у Atom и оставшейся части регулярного выражения есть точки выбора, сначала Atom сопоставляется максимально возможное число раз (или минимально возможное, если он ленивый). Все варианты оставшейся части регулярного выражения проверяются до перехода к следующему варианту последнего повторения Atom. Все варианты последнего (n-го) повторения Atom проверяются до перехода к следующему варианту предпоследнего ((n–1)-го) повторения 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 << "]: 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=[]
Утверждения
Assertion сопоставляют условия, а не подстроки входной строки. Они никогда не потребляют символы входных данных. Каждое Assertion представляет собой один из следующих вариантов
Assertion ::
^$-
\b -
\B -
(?=Disjunction) -
(?!Disjunction)
Утверждение ^ (начало строки) сопоставляется с
std::regex_constants::multiline(только C++))(начиная с C++17)
std::regex_constants::match_not_bol(только C++))Утверждение $ (конец строки) сопоставляется с
std::regex_constants::multiline(только C++))(начиная с C++17)
В двух приведённых выше утверждениях и в атоме . ниже LineTerminator — это один из следующих четырёх символов: U+000A (\n или перевод строки), U+000D (\r или возврат каретки), U+2028 (разделитель строк) или U+2029 (разделитель абзацев)
Утверждение \b (граница слова) сопоставляется с
std::regex_constants::match_not_bow(только C++))std::regex_constants::match_not_eow(только C++))Утверждение \B (не-граница слова) сопоставляется со всем, КРОМЕ следующего:
Утверждение ( ? = Disjunction ) (проверка вперёд с нулевой шириной и положительным условием) сопоставляется, если Disjunction сопоставлялась бы с входными данными в текущей позиции
Утверждение ( ? ! Disjunction ) (проверка вперёд с нулевой шириной и отрицательным условием) сопоставляется, если Disjunction НЕ сопоставлялась бы с входными данными в текущей позиции.
При сопоставлении Disjunction в обоих утверждениях Lookahead позиция не сдвигается перед сопоставлением оставшейся части регулярного выражения. Кроме того, если Disjunction может сопоставиться в текущей позиции несколькими способами, проверяется только первый из них.
ECMAScript запрещает возврат с пересмотром в дизъюнкции Lookahead, что влияет на поведение обратных ссылок из оставшейся части регулярного выражения на положительную проверку вперёд (см. пример ниже). Обратные ссылки на отрицательную проверку вперёд из оставшейся части регулярного выражения всегда не определены (так как дизъюнкция проверки вперёд должна завершиться неудачей, чтобы продолжить сопоставление).
Примечание: проверки вперёд можно использовать для создания логического И нескольких регулярных выражений (см. пример ниже).
#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 может быть одним из следующих вариантов:
Atom ::
- PatternCharacter
.-
\AtomEscape - CharacterClass
-
(Disjunction) -
(?:Disjunction)
где 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]Если за \ следует десятичное число N, первая цифра которого не равна 0, escape-последовательность считается обратной ссылкой. Значение N получают вызовом std::regex_traits::value(только C++) для каждой цифры и объединением результатов с использованием арифметики по основанию 10. Если N больше общего числа левых захватывающих скобок во всём регулярном выражении, возникает ошибка.
Когда обратная ссылка \N встречается как Atom, она сопоставляется с той же подстрокой, которая в данный момент хранится в N-м элементе массива подсовпадений.
Десятичная escape-последовательность \0 НЕ является обратной ссылкой: это escape-последовательность символа, представляющая символ NUL. За ней не может следовать десятичная цифра.
Как отмечалось выше, std::regex_replace использует $ вместо \ для обратных ссылок ($1, $2, ...).
Сопоставление с одним символом
Atom . сопоставляется с любым одним символом входной строки, кроме LineTerminator (U+000D, U+000A, U+2029 или U+2028), и потребляет его
Atom PatternCharacter, где PatternCharacter — это любой SourceCharacter, КРОМЕ символов ^ $ \ . * + ? ( ) [ ] { } |, сопоставляется с одним символом входных данных и потребляет его, если он равен этому PatternCharacter.
Равенство для этого и всех остальных вариантов сопоставления с одним символом определяется следующим образом:
std::regex_constants::icase, символы считаются равными, если равны возвращаемые значения std::regex_traits::translate_nocase (только C++).std::regex_constants::collate, символы считаются равными, если равны возвращаемые значения std::regex_traits::translate (только C++).operator== возвращает true.Каждый Atom, состоящий из символа экранирования \, за которым следует CharacterEscape, а также специальная десятичная escape-последовательность \0, сопоставляется с одним символом входных данных и потребляет его, если он равен символу, представленному CharacterEscape. Распознаются следующие escape-последовательности символов:
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; эта escape-последовательность символа сопоставляется с символом, кодовая единица которого равна остатку от деления значения кодовой единицы 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). Эта escape-последовательность символа сопоставляется с символом, кодовая единица которого равна числовому значению двухзначного шестнадцатеричного числа.
UnicodeEscapeSequence — это буква u, за которой следуют ровно четыре цифры HexDigit. Эта escape-последовательность символа сопоставляется с символом, кодовая единица которого равна числовому значению этого четырёхзначного шестнадцатеричного числа. Если значение не помещается в CharT данного std::basic_regex, возникает исключение 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
Классы символов
Atom может представлять класс символов, то есть сопоставляться с одним символом и потреблять его, если он принадлежит одной из предопределённых групп символов.
Класс символов можно задать с помощью escape-последовательности класса символов:
Atom :: \
или непосредственно
Atom ::
CharacterClassEscape-последовательности классов символов — это сокращённые обозначения некоторых распространённых классов символов:
| CharacterClassEscape | Выражение ClassName(только C++) | Значение |
|---|---|---|
d |
[[:digit:]] | цифры |
D |
[^[:digit:]] | символы, не являющиеся цифрами |
s |
[[:space:]] | пробельные символы |
S |
[^[:space:]] | символы, не являющиеся пробельными |
w |
[_[:alnum:]] | буквенно-цифровые символы и символ _ |
W |
[^_[:alnum:]] | символы, кроме буквенно-цифровых и _ |
Точное значение каждой из этих escape-последовательностей классов символов в C++ определяется через именованные классы символов, зависящие от локали, а не явным перечислением допустимых символов, как в ECMAScript.
CharacterClass — это заключённая в квадратные скобки последовательность ClassRanges, перед которой может находиться оператор отрицания ^. Если она начинается с ^, этот Atom сопоставляется с любым символом, НЕ входящим в множество символов, представленное объединением всех ClassRanges. В противном случае этот Atom сопоставляется с любым символом, входящим в множество символов, представленное объединением всех ClassRanges.
CharacterClass ::
-
[[lookahead ∉ {^}] ClassRanges] -
[^ClassRanges]
ClassRanges ::
- [пусто]
- NonemptyClassRanges
NonemptyClassRanges ::
- ClassAtom
- ClassAtom NonemptyClassRangesNoDash
- ClassAtom - ClassAtom ClassRanges
Если непустой диапазон класса имеет вид ClassAtom - ClassAtom, он сопоставляется с любым символом диапазона, определённого следующим образом: (только C++)
Первый ClassAtom должен сопоставляться с одним элементом сортировки c1, а второй ClassAtom — с одним элементом сортировки c2. Чтобы проверить, сопоставляется ли входной символ c с этим диапазоном, выполняются следующие действия:
std::regex_constants::collate выключен, сопоставление символа выполняется прямым сравнением кодовых точек: c сопоставляется, если c1 <= c && c <= c2
std::regex_constants::collate):std::regex_constants::icase, все три символа (c, c1 и c2) передаются std::regex_traits::translate_nocase
std::regex_constants::icase не задан), все три символа (c, c1 и c2) передаются std::regex_traits::translate
std::regex_traits::transform; символ c сопоставляется, если transformed c1 <= transformed c && transformed c <= transformed c2
Символ - трактуется буквально, если он
- является первым или последним символом ClassRanges
- находится в начале или конце описания диапазона, в котором символы разделены дефисом
- непосредственно следует за описанием диапазона, в котором символы разделены дефисом.
- экранирован обратной косой чертой как CharacterEscape
NonemptyClassRangesNoDash ::
- ClassAtom
- ClassAtomNoDash NonemptyClassRangesNoDash
- ClassAtomNoDash - ClassAtom ClassRanges
ClassAtom ::
-- ClassAtomNoDash
- ClassAtomExClass(только C++)
- ClassAtomCollatingElement(только C++)
- ClassAtomEquivalence(только C++)
ClassAtomNoDash ::
-
SourceCharacter, кроме символов
\ or ] or - -
\ClassEscape
Каждый ClassAtomNoDash представляет один символ — либо SourceCharacter без изменений, либо экранированный следующим образом:
ClassEscape ::
- DecimalEscape
b- CharacterEscape
- CharacterClassEscape
Специальный ClassEscape \b создаёт набор символов, сопоставляющийся с кодовой единицей U+0008 (забой). За пределами CharacterClass это граница слова — Assertion.
Использование \B и любой обратной ссылки (DecimalEscape, отличной от нуля) внутри CharacterClass является ошибкой.
В некоторых случаях символы - и ] необходимо экранировать, чтобы трактовать их как атомы. Другие символы, имеющие специальное значение вне 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. Дополнительные имена могут предоставляться системными локалями (например, jdigit или jkanji в японском языке) либо реализовываться в виде пользовательского расширения.
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::transform_primary для результата вызова std::regex_traits::lookup_collatename, также не является пустой строкой.
Первичный ключ сортировки — это ключ, не учитывающий регистр, диакритические знаки или настройки сортировки, специфичные для локали; поэтому, например, [[=a=]] сопоставляется с любым из символов: a, À, Á, Â, Ã, Ä, Å, A, à, á, â, ã, ä and å.
ClassName(только C++) ::
- ClassNameCharacter
- ClassNameCharacter ClassName
ClassNameCharacter(только C++) ::
SourceCharacter, кроме символов. = :
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/regex/ecmascript