renovations

This commit is contained in:
Ilya Kantor 2015-03-06 17:10:55 +03:00
parent 2022aafc13
commit dceccedb58
60 changed files with 1730 additions and 272 deletions

View file

@ -1,8 +1,60 @@
# Квантификаторы +, * и ?
# Квантификаторы +, *, ? и {n}
Рассмотрим ту же задачу, что и ранее -- взять телефон вида `+7(903)-123-45-67` и найти все числа в нём. Но теперь нас интересуют не цифры по отдельности, а именно числа, то есть результат вида `7, 903, 123, 45, 67`.
Для поиска цифр по отдельности нам было достаточно класса `\d`. Но здесь нужно искать *числа* -- последовательности из 1 или более цифр.
## Количество {n}
Количество повторений символа можно указать с помощью числа в фигурных скобках: `{n}`.
Такое указание называют *квантификатором* (от англ. quantifier).
У него есть несколько подформ записи:
<dl>
<dt>Точное количество: `{5}`</dt>
<dd>Регэксп <code class="pattern">\d{5}</code> обозначает ровно 5 цифр, в точности как <code class="pattern">\d\d\d\d\d</code>.
Следующий пример находит пятизначное число.
```js
//+ run
alert( "Мне 12345 лет".match (/\d{5}/) ); // "12345"
```
</dd>
<dt>Количество от-до: `{3,5}`</dt>
<dd>Для того, чтобы найти, например, числа размером от трёх до пяти знаков, нужно указать границы в фигурных скобках: <code class="pattern">\d{3,5}</code>
```js
//+ run
alert( "Мне не 12, а 1234 года".match( /\d{3,5}/ ) ); // "1234"
```
Последнее значение можно и не указывать. Тогда выражение <code class="pattern">\d{3,}</code> найдет числа, длиной от трех цифр:
```js
//+ run
alert( "Мне не 12, а 345678 лет".match( /\d{3,5}/ ) ); // "345678"
```
</dd>
</dl>
В случае с телефоном нам нужны числа -- одна или более цифр подряд. Этой задаче соответствует регулярное выражение <code class="pattern">\d{1,}</code>:
```js
//+ run
var str = "+7(903)-123-45-67";
alert( str.match( /\d{1,}/g ) ); // 7,903,123,45,67
```
## Короткие обозначения
Для самые часто востребованных квантификаторов есть специальные короткие обозначения.
[cut]
<dl>
<dt>`+`</dt>
<dd>Означает "один или более", то же что `{1,}`.
@ -20,11 +72,13 @@ alert( str.match( /\d+/g ) ); // 7,903,123,45,67
<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>.
Например, регэксп <code class="pattern">ou?r</code> найдёт <code class="match">o</code>, после которого, возможно, следует <code class="match">u</code>, а затем <code class="match">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";
var str = "Можно писать color или colour (британский вариант)";
alert( str.match( /colou?r/g ) ); // color, colour
```
@ -50,19 +104,22 @@ alert( "100 10 1".match( /\d0+/g ) ); // 100, 10
</dd>
</dl>
Эти квантификаторы -- одни из важнейших "строительных блоков" для сложных регулярных выражений, поэтому мы рассмотрим ещё примеры.
## Ещё примеры
Эти квантификаторы принадлежат к числу самых важных "строительных блоков" для сложных регулярных выражений, поэтому мы рассмотрим ещё примеры.
<dl>
<dt>Десятичная дробь (число с точкой внутри): <code class="pattern">\d+\.\d+</code></dt>
<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>
<dt>Регэксп "открывающий HTML-тег без атрибутов", такой как `<span>` или `<p>`: <code class="pattern">/&lt;[a-z]+&gt;/i</code></dt>
<dd>Пример:
```js
@ -72,7 +129,7 @@ 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>
<dt>Регэксп "открывающий HTML-тег без атрибутов" (лучше): <code class="pattern">/&lt;[a-z][a-z0-9]*&gt;/i</code></dt>
<dd>
Здесь регулярное выражение расширено: в соответствие со стандартом, HTML-тег может иметь символ на любой позиции, кроме первой, например `<h1>`.
@ -82,7 +139,7 @@ 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>
<dt>Регэксп "открывающий или закрывающий HTML-тег без атрибутов": <code class="pattern">/&lt;\/?[a-z][a-z0-9]*&gt;/i</code></dt>
<dd>В предыдущий паттерн добавили необязательный слэш <code class="pattern">/?</code> перед тегом. Его понадобилось заэкранировать, чтобы JavaScript не принял его за конец шаблона.
```js
@ -95,13 +152,11 @@ alert( "<h1>Привет!</h1>".match( /<\/?[a-z][a-z0-9]*>/gi ) ); // <h1>, </
[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>.
Так как класс `\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>?