en.javascript.info/10-regular-expressions-javascript/5-regexp-character-sets-and-ranges/article.md
2015-02-27 13:21:58 +03:00

149 lines
8.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Наборы и диапазоны [...]
Если в регулярном выражении нескольки символов или символьных классов заключены в квадратные скобки `[…]`, то это означает "искать любой символ из указанных в `[…]`".
Например, <code class="pattern">[еао]</code> означает любой символ из этих трёх: `'а'`, `'е'`, или `'о'`.
[cut]
Можно использовать квадратные скобки вместе с обычными символами.
Например:
```js
//+ run
// найти [г или т], а затем "оп"
alert( "Гоп-стоп".match( /[гт]оп/gi ) ); // "Гоп", "топ"
```
Несмотря на то, что в квадратных скобках несколько символов, в совпадении должен присутствовать *ровно один* из них.
Поэтому в примере ниже нет результатов:
```js
//+ run
// найти "В", затем [у или а], затем "ля"
alert( "Вуаля".match( /В[уа]ля/ ) ); // совпадений нет
```
Совпадение было бы, если бы после `"Ву"` шло сразу `"ля"`, например <code class="subject">Вуля</code> или если бы `"Ва"` сопровождалось `"ля"`, то есть <code class="subject">Валя</code>.
**Квадратные скобки могут также содержать *диапазоны символов*.**
Например, <code class="pattern">[a-z]</code> -- произвольный символ от `a` до `z`, <code class="pattern">[0-5]</code> -- цифра от `0` до `5`.
В примере ниже мы будем искать `"x"`, после которого идёт два раза `[0-9A-F]` -- цифра или буква от A до F:
```js
//+ run
// найдёт "xAF"
alert( "Exception 0xAF".match(/x[0-9A-F][0-9A-F]/g) );
```
Обратим внимание, в слове <code class="subject">Exception</code> есть сочетание <code class="subject">xce</code>, но оно не подошло, потому что буквы в нём маленькие, а в диапазоне -- большие.
Если хочется искать и его тоже, можно добавить в скобки диапазон `a-f`: <code class="pattern">[0-9A-Fa-f]</code>. Или же просто указать у всего регулярного выражения флаг `i`.
**Символьные классы -- всего лишь более короткие записи для диапазонов, в частности:**
<ul>
<li>**\d** -- то же самое, что <code class="pattern">[0-9]</code>,</li>
<li>**\w** -- то же самое, что <code class="pattern">[a-zA-Z0-9_]</code>,</li>
<li>**\s** -- то же самое, что <code class="pattern">[\t\n\v\f\r ]</code> плюс несколько юникодных пробельных символов.</li>
</ul>
**В квадратных скобках можно использовать и диапазоны и символьные классы -- вместе.**
Например, нам нужно найти слова в тексте. Если оно на английском -- это достаточно просто:
```js
//+ run
var str = "The sun is rising!";
alert( str.match( /\w+/g ) ); // The, sun, is, rising*!*
```
А если есть слова и на русском?
```js
//+ run
var str = "Солнце встаёт!";
alert( str.match( /\w+/g ) ); // null*!*
```
Ничего не найдено! Это можно понять, ведь <code class="pattern">\w</code> -- это именно английская букво-цифра, как можно видеть из аналога <code class="pattern">[a-zA-Z0-9_]</code>.
Чтобы находило слово на русском -- нужно использовать диапазон, например <code class="pattern">/[а-я]/</code>. А чтобы на обоих языках -- и то и другое вместе:
```js
//+ run
var str = "Солнце (the sun) встаёт!";
alert( str.match( /[\wа-я]+/gi ) ); // Солнце, the, sun, вста, т*!*
```
...Присмотритесь внимательно к предыдущему примеру! Вы видите странность? Оно не находит букву <code class="match">ё</code>, более того -- считает её разрывом в слове. Причина -- в кодировке юникод, она подробно раскрыта в главе [](/string). Буква `ё` лежит в стороне от основной кириллицы и её следует добавить в диапазон дополнительно, вот так:
```js
//+ run
var str = "Солнце (the sun) встаёт!";
alert( str.match( /[\wа-яё]+/gi ) ); // Солнце, the, sun, встаёт*!*
```
Теперь всё в порядке.
**Кроме обычных, существуют также *исключающие* диапазоны: <code class="pattern">[^…]</code>.**
Квадратные скобки, начинающиеся со знака каретки: <code class="pattern">[^…]</code> находят любой символ, *кроме указанных*.
Например:
<ul>
<li><code class="pattern">[^аеуо]</code> -- любой символ, кроме `'a'`, `'e'`, `'y'`, `'o'`</li>
<li><code class="pattern">[^0-9]</code> -- любая не-цифра, то же что `\D`</li>
<li><code class="pattern">[^\s]</code> -- любой не-пробельный символ, как и `\S`</li>
</ul>
Пример ниже ищет любые символы, кроме букв, цифр и пробелов:
```js
//+ run
alert( "alice15@gmail.com".match( /[^\d\sA-Z]/gi ) ); // "@", "."
```
**В квадратных скобках большинство специальных символов можно использовать без экранирования.**
Обычно, если мы хотим искать именно точку, а не любой символ, или именно `"\d"`, а не произвольную цифру, то мы используем экранирование: указываем `\.` или `\\d`.
Но квадратные скобки подразумевают поиск одного символа из нескольких или из диапазона. Использование некоторых специальных символов внутри них не имело бы смысла, и они воспринимаются как обычные символы.
Это касается символов:
<ul>
<li>точка <code class="pattern">'.'</code></li>
<li>плюс <code class="pattern">'+'</code></li>
<li>круглые скобки <code class="pattern">'( )'</code></li>
<li>дефис <code class="pattern">'-'</code>, если он находится в начале или конце квадратных скобок, то есть не выделяет диапазон.</li>
<li>символ каретки <code class="pattern">'^'</code>, если не находится в начале квадратных скобок, то есть кроме <code class="pattern">[\^..]</code>.</li>
<li>а также открывающая квадратная скобка <code class="pattern">'['</code></li>
</ul>
То есть, точка `"."` в квадратных скобках означает не "любой символ", а обычную точку.
Например, регэксп <code class="pattern">[-().^+]</code> ищет один из символов `-().^`. В данном контексте эти символы не являются специальными.
```js
//+ run
var re = /[-().^+]/g;
alert( "1 + 2 - 3".match(re) ); // найдёт +, -
```
...Впрочем, даже если вы решите "на всякий случай" заэкранировать эти символы, поставив перед ними обратный слэш `\` -- вреда не будет:
```js
//+ run
var re = /[\-\(\)\.\^\+]/g;
alert( "1 + 2 - 3".match(re) ); // тоже работает: +, -
```