en.javascript.info/10-regular-expressions-javascript/7-regexp-quantifiers/article.md
2015-02-27 13:21:58 +03:00

113 lines
5.1 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.

# Квантификаторы +, * и ?
Для самые часто востребованных квантификаторов есть специальные короткие обозначения.
[cut]
<dl>
<dt>`+`</dt>
<dd>Означает "один или более", то же что `{1,}`.
Например, <code class="pattern">\d+</code> находит числа -- последовательности из 1 или более цифр:
```js
//+ run
var str = "+7(903)-123-45-67";
alert( str.match( /\d+/g ) ); // 7,903,123,45,67
```
</dd>
<dt>`?`</dt>
<dd>Означает "ноль или один", то же что и `{0,1}`. По сути, делает символ необязательным.
Например, <code class="pattern">ou?r</code> найдёт <code class="match">or</code> в слове <code class="subject">color</code> и <code class="match">our</code> в его британском варианте написания <code class="subject">colour</code>.
```js
//+ run
var str = "Можно писать color или colour";
alert( str.match( /colou?r/g ) ); // color, colour
```
</dd>
<dt>`*`</dt>
<dd>Означает "ноль или более", то же что `{0,}`. То есть, символ может повторяться много раз или вообще отсутствовать.
Пример ниже находит цифру, после которой идёт один или более нулей:
```js
//+ run
alert( "100 10 1".match( /\d0*/g ) ); // 100, 10, 1
```
Сравните это с `'+'` (один или более):
```js
//+ run
alert( "100 10 1".match( /\d0+/g ) ); // 100, 10
```
</dd>
</dl>
Эти квантификаторы -- одни из важнейших "строительных блоков" для сложных регулярных выражений, поэтому мы рассмотрим ещё примеры.
<dl>
<dt>Десятичная дробь (число с точкой внутри): <code class="pattern">\d+\.\d+</code></dt>
<dd>
```js
//+ run
alert( "0 1 12.345 7890".match( /\d+\.\d+/g ) ); // 123.45
```
</dd>
<dt>Открывающий HTML-тег без атрибутов, такой как `<span>` или `<p>`: <code class="pattern">/&lt;[a-z]+&gt;/i</code></dt>
<dd>Пример:
```js
//+ run
alert( "<BODY> ... </BODY>".match ( /<[a-z]+>/gi ) ); // <BODY>
```
Это регулярное выражение ищет символ <code class="pattern">'&lt;'</code>, за которым идут одна или более букв английского алфавита, и затем <code class="pattern">'&gt;'</code>.
</dd>
<dt>Открывающий HTML-тег без атрибутов (лучше): <code class="pattern">/&lt;[a-z][a-z0-9]*&gt;/i</code></dt>
<dd>
Здесь регулярное выражение расширено: в соответствие со стандартом, HTML-тег может иметь символ на любой позиции, кроме первой, например `<h1>`.
```js
//+ run
alert( "<h1>Привет!</h1>".match( /<[a-z][a-z0-9]*>/gi ) ); // <h1>
```
</dd>
<dt>Открывающий или закрывающий HTML-тег без атрибутов: <code class="pattern">/&lt;\/?[a-z][a-z0-9]*&gt;/i</code></dt>
<dd>В предыдущий паттерн добавили необязательный слэш <code class="pattern">/?</code> перед тегом. Его понадобилось заэкранировать, чтобы JavaScript не принял его за конец шаблона.
```js
//+ run
alert( "<h1>Привет!</h1>".match( /<\/?[a-z][a-z0-9]*>/gi ) ); // <h1>, </h1>
```
</dd>
</dl>
[smart header="Точнее -- значит сложнее"]
Здесь мы видим классическую ситуацию, которая повторяется из раза в раз.
Чем точнее регулярное выражение, тем оно длиннее и сложнее.
Например, для HTML-тегов, скорее всего, подошло бы и более короткое регулярное выражение <code class="pattern">&lt;\w+&gt;</code>.
Так как класс `\w` означает "любая цифра или английская буква или _`, то под такой шаблон подойдут и не теги, например <code class="match">&lt;_&gt;</code>, однако он гораздо проще, чем <code class="pattern">&lt;[a-z][a-z0-9]*&gt;</code>.
Подойдёт ли нам <code class="pattern">&lt;\w+&gt;</code> или нужно использовать именно <code class="pattern">&lt;[a-z][a-z0-9]*&gt;</code>?
В реальной жизни допустимы оба варианта. Ответ на подобные вопросы зависит от того, насколько реально важна точность и насколько сложно потом будет отфильтровать лишние совпадения (если появятся).
[/smart]