Символьный класс: [...], [^...]
Базовый уровень Широко доступен
Эта функция хорошо зарекомендовала себя и работает на многих устройствах и версиях браузеров. Она доступна во всех браузерах с июля 2015 года.
Символьный класс соответствует любому символу из заданного или не из заданного пользовательского набора символов. Когда включен флаг v, его также можно использовать для сопоставления строк конечной длины.
Синтаксис
[]
[abc]
[A-Z]
[^]
[^abc]
[^A-Z]
// `v` mode only
[operand1&&operand2]
[operand1--operand2]
[\q{substring}]
Параметры
-
operand1,operand2 - Может быть одиночным символом, другим символьным классом, заключенным в квадратные скобки, экранированием символьного класса, экранированием Unicode-символьного класса или строкой, использующей синтаксис
\q. -
substring - Литеральная строка.
Описание
Символьный класс определяет список символов между квадратными скобками и соответствует любому символу из этого списка. Флаг v кардинально меняет способ разбора и интерпретации символьных классов. Следующие синтаксисы доступны как в режиме v, так и в режиме, отличном от v:
- Одиночный символ: соответствует самому символу.
- Диапазон символов: соответствует любому символу в инклюзивном диапазоне. Диапазон задается двумя символами, разделенными тире (
-). Первый символ должен иметь меньшее значение, чем второй. Значение символа — это его кодовая точка Unicode. Поскольку кодовые точки Unicode обычно присваиваются алфавитам по порядку,[a-z]определяет все строчные латинские символы, а[α-ω]— все строчные греческие символы. В режиме, не учитывающем Unicode, регулярные выражения интерпретируются как последовательность BMP символов. Поэтому пары суррогатов в символьных классах представляют два символа вместо одного; подробности см. ниже. - Последовательности экранирования:
\b,\-, экранирование символьных классов, экранирование Unicode-символьных классов и другие экранирования символов.
Эти синтаксисы могут встречаться любое количество раз, и представляемые ими наборы символов объединяются. Например, /[a-zA-Z0-9]/ соответствует любой букве или цифре.
Префикс ^ в символьном классе создает дополнительный класс. Например, [^abc] соответствует любому символу, кроме a, b или c. Символ ^ является литеральным символом, когда он появляется в середине символьного класса — например, [a^b] соответствует символам a, ^ и b.
Лексическая грамматика выполняет очень грубый разбор литералов регулярных выражений, поэтому она не завершает литерал регулярного выражения на символе /, который появляется внутри символьного класса. Это означает, что /[/]/ является допустимым без необходимости экранирования /.
Границы диапазона символов не должны указывать более одного символа, что происходит при использовании экранирования символьного класса. Например:
/[\s-9]/u; // SyntaxError: Invalid regular expression: Invalid character class
В режиме, не учитывающем Unicode, диапазоны символов, где одна из границ — это символьный класс, делают - литеральным символом. Это устаревший синтаксис для совместимости с веб-браузерами, и на него не следует полагаться.
/[\s-9]/.test("-"); // true
В режиме, не учитывающем Unicode, регулярные выражения интерпретируются как последовательность BMP-символов. Следовательно, пары суррогатов в символьных классах представляют два символа вместо одного.
/[😄]/.test("\ud83d"); // true
/[😄]/u.test("\ud83d"); // false
/[😄-😛]/.test("😑"); // SyntaxError: Invalid regular expression: /[😄-😛]/: Range out of order in character class
/[😄-😛]/u.test("😑"); // true
Даже если шаблон игнорирует регистр, регистр двух концов диапазона имеет значение при определении того, какие символы принадлежат диапазону. Например, шаблон /[E-F]/i соответствует только E, F, e и f, в то время как шаблон /[E-f]/i соответствует всем строчным и прописным латинским буквам ASCII (поскольку он охватывает E–Z и a–f), а также [, \, ], ^, _ и `.
Символьный класс в режиме без флага 'v'
Символьные классы в режиме, отличном от v, интерпретируют большинство символов буквально и имеют меньше ограничений относительно символов, которые они могут содержать. Например, . — это литеральный символ точки, а не шаблон. Единственными символами, которые не могут быть представлены буквально, являются \, ] и -.
- В символьных классах поддерживается большинство последовательностей экранирования, за исключением
\b,\Bи обратных ссылок.\bобозначает символ возврата на строку вместо границы слова, в то время как остальные два вызывают ошибки синтаксиса. Чтобы использовать\буквально, экранируйте его как\\. - Символ
]обозначает конец символьного класса. Чтобы использовать его буквально, экранируйте его как\]. - Символ тире (
-), используемый между двумя символами, обозначает диапазон. Когда он появляется в начале или конце символьного класса, он является литеральным символом. Он также является литеральным символом, когда используется в границах диапазона. Например,[a-]соответствует символамaи-,[!--]соответствует символам от!до-, а[--9]соответствует символам от-до9. Вы также можете экранировать его как\-, если хотите использовать его буквально где угодно.
Символьный класс в режиме 'v'
Основная идея символьных классов в режиме v остается прежней: вы по-прежнему можете использовать большинство символов буквально, использовать - для обозначения диапазонов символов и использовать последовательности экранирования. Одной из наиболее важных особенностей флага v является нотация множеств внутри символьных классов. Как упоминалось ранее, обычные символьные классы могут выражать объединения, объединяя два диапазона, например, используя [A-Z0-9] для обозначения "объединения множества [A-Z] и множества [0-9]". Однако нет простого способа представить другие операции с наборами символов, такие как пересечение и разность.
С флагом v пересечение выражается с помощью &&, а вычитание — с помощью --. Отсутствие обоих подразумевает объединение. Два операнда && или -- могут быть символом, экранированием символа, экранированием символьного класса или даже другим символьным классом. Например, чтобы выразить "словесный символ, который не является подчеркиванием", вы можете использовать [\w--_]. Вы не можете смешивать операторы на одном уровне. Например, [\w&&[A-z]--_] — это ошибка синтаксиса. Однако, поскольку вы можете вкладывать символьные классы, вы можете быть явными, написав [\w&&[[A-z]--_]] или [[\w&&[A-z]]--_] (которые оба означают [A-Za-z]). Аналогично, [AB--C] недопустимо, и вам нужно написать [A[B--C]] (что просто означает [AB]).
В режиме v экранирование Unicode-символьного класса \p может соответствовать строкам конечной длины, таким как эмодзи. Для симметрии, обычные символьные классы также могут соответствовать более чем одному символу. Чтобы записать "литеральную строку" в символьном классе, заключите строку в \q{...}. Единственный поддерживаемый здесь синтаксис регулярных выражений — это дизъюнкция — помимо этого, \q должны полностью заключать литералы (включая экранированные символы). Это гарантирует, что символьные классы могут соответствовать только строкам конечной длины с конечным числом возможностей.
В отличие от обычной дизъюнкции, порядок альтернатив внутри \q не имеет значения, как и порядок \q экранирования с остальными операндами, которые объединяются. Во время сопоставления все альтернативы, указанные в символьном классе, всегда пробуются в порядке убывания длины, поэтому сопоставление является жадным. Например, [\q{a|ab}], [\q{ab|a}], [\q{ab}a] и [a\q{ab}], примененные к "ab", все будут соответствовать "ab".
Дополнительные символьные классы [^...] не могут соответствовать строкам длиннее одного символа. Например, [\q{ab|c}] допустимо и соответствует строке "ab", но [^\q{ab|c}] недопустимо, поскольку неясно, сколько символов должно быть потреблено. Проверка выполняется путем проверки того, что все \q содержат одиночные символы, а все \p определяют свойства символов — для объединений все операнды должны быть чисто символьными; для пересечений хотя бы один операнд должен быть чисто символьным; для вычитания левый операнд должен быть чисто символьным. Проверка синтаксическая, без учета фактически указываемого набора символов, что означает, что хотя /[^\q{ab|c}--\q{ab}]/v эквивалентно /[^c]/v, оно все равно отклоняется.
Поскольку синтаксис символьных классов теперь более сложен, больше символов зарезервировано и запрещено для использования в качестве литералов.
- В дополнение к
]и\, следующие символы должны быть экранированы в символьных классах, если они представляют собой литеральные символы:(,),[,{,},/,-,|. Этот список несколько похож на список синтаксических символов, за исключением того, что^,$,*,+и?не зарезервированы внутри символьных классов, в то время как/и-не зарезервированы вне символьных классов (хотя/может разделять литерал регулярного выражения и поэтому по-прежнему требует экранирования). Все эти символы также могут быть опционально экранированы в символьных классах режимаu. - Следующие последовательности "двойных пунктуаторов" также должны быть экранированы (но они вряд ли будут иметь смысл без флага
v):&&,!!,##,$$,%%,**,++,,,,..,::,;;,<<,==,>>,??,@@,^^, ` ``,~~. Inumode, some of these characters can only appear literally within character classes and cause a syntax error when escaped. Invmode, they must be escaped when appearing in pairs, but can be optionally escaped when appearing alone. For example,/[!]/uis invalid because it's an [identity escape](/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Character_escape), but both/[!]/vand/[!]/vare valid, while/[!!]/v` недопустимо. Ссылка на литеральный символ содержит подробную таблицу того, какие символы могут быть представлены экранированными или неэкранированными.
Дополнительные классы и сопоставление без учета регистра
Сопоставление без учета регистра работает путем приведения к нижнему регистру как ожидаемого набора символов, так и сопоставляемой строки. При определении дополнительных классов важен порядок, в котором JavaScript выполняет приведение к нижнему регистру и инвертирование. Вкратце, [^...] в режиме u соответствует allCharacters - caseFold(original), в то время как в режиме v соответствует caseFold(allCharacters) - caseFold(original). Это гарантирует, что все синтаксисы дополнительных классов, включая [^...], \P, \W и т.д., взаимно уничтожаются.
Рассмотрим следующие два регулярных выражения (для упрощения предположим, что символы Unicode бывают трех видов: строчные, прописные и без регистра, и каждая прописная буква имеет уникальный строчный аналог, и наоборот):
const r1 = /\p{Lowercase_Letter}/iu;
const r2 = /[^\P{Lowercase_Letter}]/iu;
r2 — это двойное отрицание, и кажется, что оно эквивалентно r1. Но на самом деле r1 соответствует всем строчным и прописным ASCII-буквам, в то время как r2 не соответствует ни одной. Вот пошаговое объяснение:
- В
r1,\p{Lowercase_Letter}создает набор всех строчных символов. Символы в этом наборе затем приводятся к нижнему регистру, поэтому они остаются прежними. Входная строка также приводится к нижнему регистру. Следовательно,"A"и"a"оба приводятся к"a"и соответствуютr1. - В
r2,\P{Lowercase_Letter}сначала создает набор всех непрописных символов, то есть прописных букв и символов без регистра. Символы в этом наборе затем приводятся к нижнему регистру, поэтому набор символов становится всеми строчными буквами и символами без регистра.[^...]инвертирует совпадение, заставляя его соответствовать любому, что не находится в этом наборе, то есть прописной букве. Однако ввод все равно приводится к нижнему регистру, поэтому"A"приводится к"a"и не соответствуетr2.
Основное наблюдение здесь заключается в том, что после того, как [^...] инвертирует совпадение, ожидаемый набор символов может не быть подмножеством набора приводимых к нижнему регистру символов Unicode, что приводит к тому, что вход, приведенный к нижнему регистру, не попадает в ожидаемый набор символов. В режиме v набор всех символов также приводится к нижнему регистру. Сам символьный класс \P также работает немного иначе в режиме v (см. экранирование Unicode-символьного класса). Все это гарантирует, что [^\P{Lowercase_Letter}] и \p{Lowercase_Letter} строго эквивалентны.
Примеры
Сопоставление шестнадцатеричных цифр
Следующая функция определяет, содержит ли строка допустимое шестнадцатеричное число:
function isHexadecimal(str) {
return /^[0-9A-F]+$/i.test(str);
}
isHexadecimal("2F3"); // true
isHexadecimal("beef"); // true
isHexadecimal("undefined"); // false
Использование пересечения
Следующая функция сопоставляет греческие буквы.
function greekLetters(str) {
return str.match(/[\p{Script_Extensions=Greek}&&\p{Letter}]/gv);
}
// 𐆊 is U+1018A GREEK ZERO SIGN
greekLetters("π𐆊P0零αAΣ"); // [ 'π', 'α', 'Σ' ]
Использование вычитания
Следующая функция соответствует всем не-ASCII-цифрам.
function nonASCIINumbers(str) {
return str.match(/[\p{Decimal_Number}--\d]/gv);
}
// 𑜹 is U+11739 AHOM DIGIT NINE
nonASCIINumbers("𐆊0零1𝟜𑜹a"); // [ '𝟜', '𑜹' ]
Сопоставление строк
Следующая функция соответствует всем последовательностям разрыва строки, включая символы разрыва строки и последовательность \r\n (CRLF). Порядок, в котором указаны альтернативы, не имеет значения, поскольку самая длинная альтернатива, \r\n, всегда имеет приоритет.
function getLineTerminatorSequences(str) {
return str.match(/[\r\n\u2028\u2029\q{\r\n}]/gv);
}
getLineTerminatorSequences(`
A poem\r
Is split\rInto many
Stanzas
`); // ['\n', '\r\n', '\r', '\n', '\n']
Это регулярное выражение в точности эквивалентно /(?:\r\n|\r|\n|\u2028|\u2029)/gu или /(?:\r\n|[\r\n\u2028\u2029])/gu. Однако в обычной дизъюнкции порядок альтернатив имеет значение, поэтому \r\n должен быть указан первым, чтобы он имел приоритет. Использование символьного класса не только короче, но и позволяет избежать этой ловушки.
Наиболее полезный случай \q{} — при выполнении вычитания и пересечения. Ранее это было возможно с помощью нескольких просмотров вперед. Следующая функция сопоставляет флаги, которые не являются флагами США, Китая, России, Великобритании и Франции.
function notUNSCPermanentMember(flag) {
return /^[\p{RGI_Emoji_Flag_Sequence}--\q{🇺🇸|🇨🇳|🇷🇺|🇬🇧|🇫🇷}]$/v.test(flag);
}
notUNSCPermanentMember("🇺🇸"); // false
notUNSCPermanentMember("🇩🇪"); // true
Этот пример в основном эквивалентен /^(?!🇺🇸|🇨🇳|🇷🇺|🇬🇧|🇫🇷)\p{RGI_Emoji_Flag_Sequence}$/v, за исключением, возможно, лучшей производительности.
Спецификации
Совместимость с браузерами
| Настольные компьютеры | Мобильные устройства | Сервер | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on iOS | Samsung Internet | WebView Android | WebView on iOS | Bun | Deno | Node.js | |
character_class |
1 |
12 |
1 |
5 |
1 |
18 |
4 |
10.1 |
1 |
1.0 |
4.4 |
1 |
1.0.0 |
1.0 |
0.10.0 |
См. также
- Руководство по символьным классам
- Регулярные выражения
- Экранирование символьного класса:
\d,\D,\w,\W,\s,\S - Экранирование Unicode-символьного класса:
\p{...},\P{...} - Литеральный символ:
a,b - Экранирование символа:
\n,\u{...} - Дизъюнкция:
| - Флаг v для RegExp с нотацией множеств и свойствами строк на v8.dev (2022)
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Regular_expressions/Character_class