Изменённая грамматика регулярных выражений ECMAScript
Эта страница описывает грамматику регулярных выражений, используемую при создании std::basic_regex с syntax_option_type установленным в ECMAScript (по умолчанию). Смотрите syntax_option_type для других поддерживаемых грамматик регулярных выражений.
Грамматика регулярных выражений 3 в C++ основана на грамматике ECMAScript-262 с изменениями, отмеченными (только для C++) ниже.
Обзор
Изменённая грамматика регулярных выражений в основном соответствует грамматике ECMAScript RegExp с расширением типа POSIX для локали в разделе ClassAtom. Внесены некоторые уточнения по проверке на равенство и анализу чисел. Для многих примеров здесь вы можете попробовать эквивалент в консоли вашего браузера:
function match(s, re) { return s.match(new RegExp(re)); }В стандарте «нормативные ссылки» указывают на ECMAScript 3. Мы ссылаемся на ECMAScript 5.1, поскольку это версия с незначительными изменениями по сравнению с ECMAScript 3, а также имеет HTML-версию. Для обзора особенностей диалекта обратитесь к руководству MDN по JavaScript RegExp.
Альтернативы
Шаблон регулярного выражения представляет собой последовательность одного или более Альтернатив, разделённых оператором дизъюнкции | (другими словами, оператор дизъюнкции имеет наименьший приоритет).
Шаблон ::
ДизъюнкцияДизъюнкция ::
- Альтернатива
-
Альтернатива
|Дизъюнкция
Шаблон сначала пытается пропустить Дизъюнкцию и сопоставить левую Альтернативу, за которой следует остальная часть регулярного выражения (после Дизъюнкции).
Если это не удаётся, он пытается пропустить левую Альтернативу и сопоставить правую Дизъюнкцию (за которой следует остальная часть регулярного выражения).
Если у левой Альтернативы, правой Дизъюнкции и оставшейся части регулярного выражения есть точки выбора, все варианты в оставшейся части выражения проверяются, прежде чем перейти к следующему варианту в левой Альтернативе. Если варианты в левой Альтернативе исчерпаны, вместо левой Альтернативы проверяется правая Дизъюнкция.
Любые группирующие скобки внутри пропущенной Альтернативы создают пустые подстроки.
#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 Alernative 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=[]
Термы
Каждая Альтернатива либо пуста, либо является последовательностью Термов (без разделителей между Термами).
Альтернатива ::
- [пусто]
- Альтернатива Терм
Пустая Альтернатива всегда соответствует и не потребляет входных данных.
Последовательные Термы пытаются одновременно сопоставить последовательные части входных данных.
Если у левой Альтернативы, правого Терма и оставшейся части регулярного выражения есть точки выбора, все варианты в оставшейся части выражения проверяются, прежде чем перейти к следующему варианту в правом Терме, и все варианты в правом Терме проверяются, прежде чем перейти к следующему варианту в левой Альтернативе.
#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 Alernative matched first
show_matches("abc", "|abc"); // left Alernative 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]
Квантификаторы
- Каждый Терм — это либо Утверждение (см. ниже), либо Атом (см. ниже), либо Атом, непосредственно за которым следует Квантификатор
Терм ::
- Утверждение
- Атом
- Атом Квантификатор
Каждый Квантификатор — это либо жадный квантификатор (состоящий только из одного КвантификаторногоПрефикса), либо нежадный квантификатор (состоящий из одного КвантификаторногоПрефикса, за которым следует вопросительный знак ?).
Квантификатор ::
- КвантификаторныйПрефикс
- КвантификаторныйПрефикс
?
Каждый КвантификаторныйПрефикс определяет два числа: минимальное и максимальное количество повторений, как указано ниже:
| КвантификаторныйПрефикс | Минимум | Максимум |
|---|---|---|
* | ноль | бесконечность |
+ | один | бесконечность |
? | ноль | один |
{ ДесятичныеЦифры } | значение ДесятичныхЦифр | значение ДесятичныхЦифр |
{ ДесятичныеЦифры , } | значение ДесятичныхЦифр | бесконечность |
{ ДесятичныеЦифры , ДесятичныеЦифры } | значение ДесятичныхЦифр до запятой | значение ДесятичныхЦифр после запятой |
Значения отдельных ДесятичныхЦифр получаются путём вызова std::regex_traits::value(только для C++) для каждой цифры.
Атом, за которым следует Квантификатор, повторяется указанное количество раз. Квантификатор может быть нежадным, в этом случае шаблон Атома повторяется как можно реже, но всё ещё соответствует остальной части регулярного выражения, или он может быть жадным, в этом случае шаблон Атома повторяется как можно чаще, но всё ещё соответствует остальной части регулярного выражения.
Повторяется шаблон Атома, а не входящие данные, которым он соответствует, поэтому разные повторения Атома могут соответствовать разным подстрокам входных данных.
Если у Атома и оставшейся части регулярного выражения есть точки выбора, Атом сначала сопоставляется как можно чаще (или как можно реже, если нежадный). Все варианты в оставшейся части регулярного выражения проверяются, прежде чем перейти к следующему варианту в последнем повторении Атома. Все варианты в последнем (n-м) повторении Атома проверяются, прежде чем перейти к следующему варианту в предпоследнем (n-1)-м повторении Атома; в этот момент может оказаться, что больше или меньше повторений Атома теперь возможно; эти варианты исчерпываются (снова, начиная с как можно меньшего или большего числа) прежде чем перейти к следующему варианту в (n-1)-м повторении Атома и так далее.
Каптуры Атома очищаются каждый раз, когда он повторяется (см. пример "(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 -
(?=Дизъюнкция) -
(?!Дизъюнкция)
Утверждение ^ (начало строки) соответствует
std::regex_constants::multiline(только для C++) включено)(с C++17)
Утверждение $ (конец строки) соответствует
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 (отрицательная граница слова) соответствует ВСЕМУ, КРОМЕ следующего:
Утверждение ( ? = Дизъюнкция ) (положительный просмотр вперёд нулевой длины) соответствует, если Дизъюнкция будет соответствовать входным данным в текущей позиции.
Утверждение ( ? ! Дизъюнкция ) (отрицательный просмотр вперёд нулевой длины) соответствует, если Дизъюнкция не будет соответствовать входным данным в текущей позиции.
Для обоих утверждений Lookahead, при сопоставлении Дизъюнкции, позиция не сдвигается до сопоставления остальной части регулярного выражения. Кроме того, если Дизъюнкция может соответствовать текущей позиции несколькими способами, пытается только первый.
ECMAScript запрещает обратное отслеживание в дизъюнкциях lookahead, что влияет на поведение обратных ссылок в положительное lookahead из остальной части регулярного выражения (см. пример ниже). Обратные ссылки в отрицательное lookahead из остальной части регулярного выражения всегда неопределены (поскольку дизъюнкция lookahead должна завершиться неудачей, чтобы продолжить).
Примечание: утверждения 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=[]Атомы
Атом может быть одним из следующих:
Атом ::
- СимволПатерна
-
. -
\ЭкранированиеАтома - КлассСимволов
-
(Дизъюнкция) -
(?:Дизъюнкция)
где ЭкранированиеАтома ::
- ДесятичныйЭкранирование
- ЭкранированиеСимвола
- ЭкранированиеКлассаСимволов
Разные виды атомов оцениваются по-разному.
Подвыражения
Атом ( Дизъюнкция ) — это помеченное подвыражение: оно выполняет Дизъюнкцию и сохраняет копию подстроки входного значения, которая была использована Дизъюнкцией, в массиве подсоответствий в индексе, соответствующем числу раз, когда левая открывающая скобка ( помеченных подвыражений была встречена в регулярном выражении в данный момент.
Помимо возврата в std::match_results, захваченные подсоответствия доступны как обратные ссылки (\1, \2, ...) и могут быть использованы в регулярных выражениях. Обратите внимание, что std::regex_replace использует $ вместо \ для обратных ссылок ($1, $2, ...) таким же образом, как String.prototype.replace (ECMA-262, часть 15.5.4.11).
Атом ( ? : Дизъюнкция ) (непомечаемое подвыражение) просто оценивает Дизъюнкцию и не сохраняет её результаты в подсоответствиях. Это чисто лексическое группирование.
Обратные ссылки
ДесятичныйЭкранирование ::
ДесятичнаяЦелаяЛитеральнаяКонстанта [lookahead ∉ ДесятичнаяЦифра]Если \ следует за десятичным числом N, первая цифра которого не 0, то последовательность экранирования считается обратной ссылкой. Значение N получается путём вызова std::regex_traits::value(только для C++) для каждой цифры и объединения их результатов с использованием десятичной арифметики. Ошибка, если N больше общего числа левых открывающих скобок в регулярном выражении.
Когда обратная ссылка \N появляется как Атом, она соответствует той же подстроке, что и в настоящее время хранится в N-том элементе массива подсоответствий.
Десятичное экранирование \0 НЕ является обратной ссылкой: это экранирование символа, представляющее NUL символ. После него не может следовать десятичная цифра.
Как и выше, обратите внимание, что std::regex_replace использует $ вместо \ для обратных ссылок ($1, $2, ...).
Сопоставления единичных символов
Атом . соответствует и потребляет любой один символ из входной строки, за исключением СимволаПереводаСтроки (U+000D, U+000A, U+2029, или U+2028)
Атом СимволПатерна, где СимволПатерна — любой СимволИсточника, ЗА ИСКЛЮЧЕНИЕМ символов ^ $ \ . * + ? ( ) [ ] { } |, соответствует и потребляет один символ из ввода, если он равен этому СимволуПатерна.
Равенство для этого и всех других сопоставлений единичных символов определяется следующим образом:
std::regex_constants::icase установлено, символы равны, если возвращаемые значения std::regex_traits::translate_nocase равны (только для C++).std::regex_constants::collate установлено, символы равны, если возвращаемые значения std::regex_traits::translate равны (только для C++).operator== возвращает true.
Каждый Атом, состоящий из символа экранирования \ и ЭкранированияСимвола, а также специального ДесятичногоЭкранирования \0, соответствует и потребляет один символ из ввода, если он равен символу, представленному ЭкранированиемСимвола. Признаются следующие последовательности экранирования символов:
ЭкранированиеСимвола ::
- ЭкранированиеУправляющегоСимвола
-
cУправляющаяБуква - ШестнадцатеричноеЭкранирование
- UnicodeЭкранирование
- ИдентичноеЭкранирование
Здесь ЭкранированиеУправляющегоСимвола — один из следующих пяти символов: f n r t v
| ЭкранированиеУправляющегоСимвола | Код Юникода | Наименование |
|---|---|---|
f | U+000C | формат подачи |
n | U+000A | новая строка |
r | U+000D | возврат каретки |
t | U+0009 | горизонтальная табуляция |
v | U+000B | вертикальная табуляция |
УправляющаяБуква — это любая строчная или прописная буква ASCII, и это экранирование символа соответствует символу, код Юникода которого равен остатку от деления значения кода Юникода УправляющейБуквы на 32. Например, \cD и \cd оба соответствуют коду Юникода U+0004 (EOT), так как 'D' — это U+0044 и 0x44 % 32 == 4, а 'd' — это U+0064 и 0x64 % 32 == 4.
ШестнадцатеричноеЭкранирование — это буква x и ровно две ШестнадцатеричныеЦифры (где ШестнадцатеричнаяЦифра — одна из 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F). Это экранирование символа соответствует символу, код Юникода которого равен числовому значению двухзначного шестнадцатеричного числа.
UnicodeЭкранирование — это буква u и ровно четыре ШестнадцатеричныеЦифры. Это экранирование символа соответствует символу, код Юникода которого равен числовому значению этого четырёхзначного шестнадцатеричного числа. Если значение не помещается в этом std::basic_regex, CharT, выбрасывается std::regex_error (только для C++).
ИдентичноеЭкранирование может быть любым небуквенно-цифровым символом: например, другой обратный слэш. Оно соответствует символу как есть.
#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:]] | символы, отличные от буквенно-цифровых или _ |
КлассСимволов — это заключённая в квадратные скобки последовательность ДиапазоновКлассов, необязательно начинающаяся с оператора отрицания ^. Если она начинается с ^, этот Атом соответствует любому символу, который НЕ входит в множество символов, представленных объединением всех ДиапазоновКлассов. В противном случае этот Атом соответствует любому символу, который ВХОДИТ в множество символов, представленное объединением всех ДиапазоновКлассов.
КлассСимволов ::
-
[[lookahead ∉ {^}] ДиапазоновКлассов] -
[^ДиапазоновКлассов]
ДиапазоныКлассов ::
- [пусто]
- НепустыеДиапазоныКлассов
НепустыеДиапазоныКлассов ::
- АтомКласса
- АтомКласса НепустыеДиапазоныКлассовБезДефиса
- АтомКласса - АтомКласса ДиапазоныКлассов
Если непустой диапазон класса имеет вид ClassAtom - ClassAtom, он соответствует любому символу из диапазона, определённого следующим образом: (только для C++)
Первый АтомКласса должен соответствовать одному элементу сортировки c1, а второй АтомКласса — одному элементу сортировки 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
- начальный или конечный ClassAtom диапазона, заданного через дефис
- сразу следует за диапазоном, заданным через дефис.
- экранируется обратной косой чертой как 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/w/cpp/regex/ecmascript