fixes, renovations
This commit is contained in:
parent
3889056599
commit
bc34b2fc9d
133 changed files with 189 additions and 10 deletions
|
@ -0,0 +1,21 @@
|
|||
Регулярное выражение для поиска 3-значного цвета: <code class="pattern">/#[a-f0-9]{3}/i</code>.
|
||||
|
||||
Нужно добавить ещё три символа, причём нужны именно три, четыре или семь символов не нужны. Эти три символа либо есть, либо нет.
|
||||
|
||||
Самый простой способ добавить -- просто дописать в конец регэкспа: <code class="pattern">/#[a-f0-9]{3}([a-f0-9]{3})?/i</code>
|
||||
|
||||
Можно поступить и хитрее: <code class="pattern">/#([a-f0-9]{3}){1,2}/i</code>.
|
||||
|
||||
Здесь регэксп <code class="pattern">[a-f0-9]{3}</code> заключён в скобки, чтобы квантификатор <code class="pattern">{1,2}</code> применялся целиком ко всей этой структуре.
|
||||
|
||||
В действии:
|
||||
```js
|
||||
//+ run
|
||||
var re = /#([a-f0-9]{3}){1,2}/gi;
|
||||
|
||||
var str = "color: #3f3; background-color: #AA00ef; and: #abcd";
|
||||
|
||||
alert( str.match(re) ); // #3f3 #AA0ef #abc
|
||||
```
|
||||
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
# Найдите цвет в формате #abc или #abcdef
|
||||
|
||||
Напишите регулярное выражение, которое находит цвет в формате `#abc` или `#abcdef`. То есть, символ `#`, после которого идут 3 или 6 шестнадцатиричных символа.
|
||||
|
||||
Пример использования:
|
||||
```js
|
||||
var re = /* ваш регэксп */
|
||||
|
||||
var str = "color: #3f3; background-color: #AA00ef; and: #abcd";
|
||||
|
||||
alert( str.match(re) ); // #3f3 #AA0ef
|
||||
```
|
||||
|
||||
P.S. Значения из четырёх и более букв, такие как `#abcd` мы в этой задаче также учитываем, но берём из них только необходимые для совпадения символы, то есть `#abc`.
|
|
@ -0,0 +1,53 @@
|
|||
Регулярное выражение для числа, возможно, дробного и отрицательного: <code class="pattern">-?\d+(\.\d+)?</code>. Мы уже разбирали его в предыдущих задачах.
|
||||
|
||||
Оператор -- это <code class="pattern">[-+*/]</code>. Заметим, что дефис <code class="pattern">-</code> идёт в списке первым, так как на любой позиции, кроме первой и последней, он имеет специальный смысл внутри <code class="pattern">[...]</code>, и его понадобилось бы экранировать.
|
||||
|
||||
Кроме того, когда мы оформим это в JavaScript-синтаксис <code class="pattern">/.../</code> -- понадобится заэкранировать слэш <code class="pattern">/</code>.
|
||||
|
||||
Нам нужно число, затем оператор, затем число, и необязательные пробелы между ними.
|
||||
|
||||
Полное регулярное выражение будет таким: <code class="pattern">-?\d+(\.\d+)?\s*[-+*/]\s*-?\d+(\.\d+)?</code>.
|
||||
|
||||
Чтобы получить результат в виде массива, добавим скобки вокруг тех данных, которые нам интересны, то есть -- вокруг чисел и оператора: <code class="pattern">(-?\d+(\.\d+)?)\s*([-+*/])\s*(-?\d+(\.\d+)?)</code>.
|
||||
|
||||
Посмотрим в действии:
|
||||
```js
|
||||
//+ run
|
||||
var re = /(-?\d+(\.\d+)?)\s*([-+*\/])\s*(-?\d+(\.\d+)?)/;
|
||||
|
||||
alert( "1.2 + 12".match(re) );
|
||||
```
|
||||
|
||||
Итоговый массив будет включать в себя компоненты:
|
||||
|
||||
<ul>
|
||||
<li>`result[0] == "1.2 + 12"` (вначале всегда полное совпадение)</li>
|
||||
<li>`result[1] == "1"` (первая скобка)</li>
|
||||
<li>`result[2] == "2"` (вторая скобка -- дробная часть `(\.\d+)?`)</li>
|
||||
<li>`result[3] == "+"` (...)</li>
|
||||
<li>`result[4] == "12"` (...)</li>
|
||||
<li>`result[5] == undefined` (последняя скобка, но у второго числа дробная часть отсутствует)</li>
|
||||
</ul>
|
||||
|
||||
Нам из этого массива нужны только числа и оператор. А, скажем, дробная часть сама по себе -- не нужна.
|
||||
|
||||
Уберём её из запоминания, добавив в начало скобки <code class="pattern">?:</code>, то есть: <code class="pattern">(?:\.\d+)?</code>.
|
||||
|
||||
Итого, решение:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
function parse(expr) {
|
||||
var re = /(-?\d+(?:\.\d+)?)\s*([-+*\/])\s*(-?\d+(?:\.\d+)?)/;
|
||||
|
||||
var result = expr.match(re);
|
||||
|
||||
if (!result) return;
|
||||
result.shift();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
alert( parse("-1.23 * 3.45") ); // -1.23, *, 3.45
|
||||
```
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
# Разобрать выражение
|
||||
|
||||
Арифметическое выражение состоит из двух чисел и операции между ними, например:
|
||||
<ul>
|
||||
<li>`1 + 2`</li>
|
||||
<li>`1.2 * 3.4`</li>
|
||||
<li>`-3 / -6`</li>
|
||||
<li>-2 - 2`</li>
|
||||
</ul>
|
||||
|
||||
Список операций: `"+"`, `"-"`, `"*"` и `"/"`.
|
||||
|
||||
Также могут присутсововать пробелы вокруг оператора и чисел.
|
||||
|
||||
Напишите функцию, которая будет получать выражение и возвращать массив из трёх аргументов:
|
||||
<ol>
|
||||
<li>Первое число.</li>
|
||||
<li>Оператор.</li>
|
||||
<li>Второе число.</li>
|
||||
</ul>
|
151
11-regular-expressions-javascript/9-regexp-groups/article.md
Normal file
151
11-regular-expressions-javascript/9-regexp-groups/article.md
Normal file
|
@ -0,0 +1,151 @@
|
|||
# Скобочные группы
|
||||
|
||||
Часть шаблона может быть заключена в скобки <code class="pattern">(...)</code>. Такие выделенные части шаблона называют "скобочными выражениями" или "скобочными группами".
|
||||
|
||||
У такого выделения есть два эффекта:
|
||||
<ol>
|
||||
<li>Он позволяет выделить часть совпадения в отдельный элемент массива при поиске через [String#match](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/match) или [RegExp#exec](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec).</li>
|
||||
<li>Если поставить квантификатор после скобки, то он применится *ко всей скобке*, а не всего лишь к одному символу.</li>
|
||||
</ol>
|
||||
|
||||
[cut]
|
||||
|
||||
## Пример
|
||||
|
||||
В примере ниже, шаблон <code class="pattern">(go)+</code> находит один или более повторяющихся <code class="pattern">'go'</code>:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
alert( 'Gogogo now!'.match(/(go)+/i ); // "Gogogo"
|
||||
```
|
||||
|
||||
Без скобок, шаблон <code class="pattern">/go+/</code> означал бы <code class="subject">g</code>, после которого идёт одна или более <code class="subject">o</code>, например: <code class="match">goooo</code>. А скобки "группируют" <code class="pattern">(go)</code> вместе.
|
||||
|
||||
|
||||
## Содержимое группы
|
||||
|
||||
Скобки нумеруются слева направо. Поисковой движок запоминает содержимое каждой скобки и позволяет обращаться к нему -- в шаблоне и строке замены и, конечно же, в результатах.
|
||||
|
||||
Например, найти HTML-тег можно шаблоном <code class="pattern"><.*?></code>.
|
||||
|
||||
После поиска мы захотим что-то сделать с результатом. Для удобства заключим содержимое `<...>` в скобки: <code class="pattern"><(.*?)></code>. Тогда оно будет доступно отдельно.
|
||||
|
||||
При поиске методом [String#match](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/match) в результирующем массиве будет сначала всё совпадение, а далее -- скобочные группы. В шаблоне <code class="pattern"><(.*?)></code> скобочная группа только одна:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var str = '<h1>Привет, мир!</h1>';
|
||||
var reg = /<(.*?)>/;
|
||||
|
||||
alert( str.match(reg) ); // массив: <h1>, h1
|
||||
```
|
||||
|
||||
Заметим, что метод [String#match](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/match) выдаёт скобочные группы только при поиске без флага `/.../g`. В примере выше он нашёл только первое совпадение <code class="match"><h1></code>, а закрывающий <code class="match"></h1></code> не нашёл, поскольку без флага `/.../g` ищется только первое совпадение.
|
||||
|
||||
Для того, чтобы искать и с флагом `/.../g` и со скобочными группами, используется метод [RegExp#exec](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec):
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var str = '<h1>Привет, мир!</h1>';
|
||||
var reg = /<(.*?)>/g;
|
||||
|
||||
var match;
|
||||
|
||||
while ((match = reg.exec(str)) !== null) {
|
||||
// сначала выведет первое совпадение: <h1>,h1
|
||||
// затем выведет второе совпадение: </h1>,/h1
|
||||
alert(match);
|
||||
}
|
||||
```
|
||||
|
||||
Теперь найдено оба совпадения <code class="pattern"><(.*?)></code>, каждое -- массив из полного совпадения и скобочных групп (одна в данном случае).
|
||||
|
||||
## Вложенные группы
|
||||
Скобки могут быть и вложенными. В этом случае нумерация также идёт слева направо.
|
||||
|
||||
Например, при поиске тега в <code class="subject"><span class="my"></code> нас может интересовать:
|
||||
|
||||
<ol>
|
||||
<li>Содержимое тега целиком: `span class="my"`.</li>
|
||||
<li>В отдельную переменную для удобства хотелось бы поместить тег: `span`.</li>
|
||||
<li>Также может быть удобно отдельно выделить атрибуты `class="my"`.</li>
|
||||
</ol>
|
||||
|
||||
Добавим скобки в регулярное выражение:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var str = '<span class="my">';
|
||||
|
||||
reg = /<(([a-z]+)\s*([^>]*))>/;
|
||||
|
||||
alert( str.match(reg) ); // <span class="my">, span, s
|
||||
```
|
||||
|
||||
Вот так выглядят скобочные группы:
|
||||
|
||||
<img src="regexp-nested-groups.svg">
|
||||
|
||||
На нулевом месте -- всегда совпадение полностью, далее -- группы. Нумерация всегда идёт слева направо, по открывающей скобке.
|
||||
|
||||
В данном случае получилось, что группа 1 включает в себя содержимое групп 2 и 3. Это совершенно нормальная ситуация, которая возникает, когда нужно выделить что-то отдельное внутри большей группы.
|
||||
|
||||
**Даже если скобочная группа необязательна и не входит в совпадение, соответствующий элемент массива существует (и равен `undefined`).**
|
||||
|
||||
Например, рассмотрим регэксп <code class="pattern">a(z)?(c)?</code>. Он ищет `"a"`, за которой не обязательно идёт буква `"z"`, за которой необязательно идёт буква `"c"`.
|
||||
|
||||
Если напустить его на строку из одной буквы `"a"`, то результат будет таков:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
match = 'a'.match(/a(z)?(c)?/)
|
||||
|
||||
alert( match.length ); // 3
|
||||
alert( match[0] ); // a
|
||||
alert( match[1] ); // undefined
|
||||
alert( match[2] ); // undefined
|
||||
```
|
||||
|
||||
Массив получился длины `3`, но все скобочные группы -- `undefined`.
|
||||
|
||||
А теперь более сложная ситуация, строка <code class="subject">ack</code>:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
match = 'ack'.match(/a(z)?(c)?/)
|
||||
|
||||
alert( match.length ); // 3
|
||||
alert( match[0] ); // ac, всё совпадение
|
||||
alert( match[1] ); // undefined, для (z)? ничего нет
|
||||
alert( match[2] ); // c
|
||||
```
|
||||
|
||||
Длина массива результатов по-прежнему `3`. Она постоянна. А вот для скобочной группы <code class="pattern">(z)?</code> в ней ничего нет, поэтому результат: `["ac", undefined, "c"]`.
|
||||
|
||||
## Исключение из запоминания через ?:
|
||||
|
||||
Бывает так, что скобки нужны, чтобы квантификатор правильно применился, а вот запоминать её в массиве не нужно.
|
||||
|
||||
Скобочную группу можно исключить из запоминаемых и нумеруемых, добавив в её начало <code class="pattern">?:</code>.
|
||||
|
||||
|
||||
Например, мы хотим найти <code class="pattern">(go)+</code>, но содержимое скобок (`go`) в отдельный элемент массива выделять не хотим.
|
||||
|
||||
Для этого нужно сразу после открывающей скобки поставить `?:`, то есть: <code class="pattern">(?:go)+</code>.
|
||||
|
||||
Например:
|
||||
|
||||
```js
|
||||
//+ run
|
||||
var str = "Gogo John!";
|
||||
*!*
|
||||
var reg = /(?:go)+ (\w+)/i;
|
||||
*/!*
|
||||
|
||||
var result = str.match(reg);
|
||||
|
||||
alert( result.length ); // 2
|
||||
alert( result[1] ); // John
|
||||
```
|
||||
|
||||
В примере выше массив результатов имеет длину `2` и содержит только полное совпадение и результат <code class="pattern">(\w+)</code>. Это удобно в тех случаях, когда содержимое скобок нас не интересует.
|
|
@ -0,0 +1,49 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="320px" height="130px" viewBox="0 0 320 130" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
||||
<!-- Generator: bin/sketchtool 1.3 (252) - http://www.bohemiancoding.com/sketch -->
|
||||
<title>regexp-nested-groups.svg</title>
|
||||
<desc>Created with bin/sketchtool.</desc>
|
||||
<defs></defs>
|
||||
<g id="combined" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
||||
<g id="regexp-nested-groups.svg" sketch:type="MSArtboardGroup">
|
||||
<text id="<(([a-z]+)\s*([^>]*)" sketch:type="MSTextLayer" font-family="Consolas" font-size="24" font-weight="normal">
|
||||
<tspan x="20" y="75" fill="#8A704D"><</tspan>
|
||||
<tspan x="33.1953125" y="75" fill="#DC2022">((</tspan>
|
||||
<tspan x="59.5859375" y="75" fill="#8A704D">[a-z]+</tspan>
|
||||
<tspan x="138.757812" y="75" fill="#DC2022">)</tspan>
|
||||
<tspan x="151.953125" y="75" fill="#8A704D">\s*</tspan>
|
||||
<tspan x="191.539062" y="75" fill="#DC2022">(</tspan>
|
||||
<tspan x="204.734375" y="75" fill="#8A704D">[^>]*</tspan>
|
||||
<tspan x="270.710938" y="75" fill="#D0011B">))</tspan>
|
||||
<tspan x="297.101562" y="75" fill="#8A704D">></tspan>
|
||||
</text>
|
||||
<path d="M42.5,45.6458333 L42.5,29.3541667" id="Line" stroke="#D0011B" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
|
||||
<path d="M290.5,45.6458333 L290.5,29.3541667" id="Line-2" stroke="#D0011B" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
|
||||
<path d="M42.5,28.5 L290.5,28.5" id="Line" stroke="#D0011B" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
|
||||
<path d="M52.5,101.645833 L52.5,85.3541667" id="Line-5" stroke="#D0011B" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
|
||||
<path d="M145.5,101.645833 L145.5,85.3541667" id="Line-4" stroke="#D0011B" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
|
||||
<path d="M52.5,102.5 L145.5,102.5" id="Line-3" stroke="#D0011B" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
|
||||
<text id="1" sketch:type="MSTextLayer" font-family="Consolas" font-size="20" font-weight="normal" fill="#D0011B">
|
||||
<tspan x="29" y="44">1</tspan>
|
||||
</text>
|
||||
<text id="span-class="my"" sketch:type="MSTextLayer" font-family="Consolas" font-size="20" font-weight="normal" fill="#417505">
|
||||
<tspan x="82" y="26">span class="my"</tspan>
|
||||
</text>
|
||||
<text id="2" sketch:type="MSTextLayer" font-family="Consolas" font-size="20" font-weight="normal" fill="#D0011B">
|
||||
<tspan x="40" y="101">2</tspan>
|
||||
</text>
|
||||
<text id="span" sketch:type="MSTextLayer" font-family="Consolas" font-size="20" font-weight="normal" fill="#417505">
|
||||
<tspan x="73" y="117">span</tspan>
|
||||
</text>
|
||||
<path d="M197.5,101.645833 L197.5,85.3541667" id="Line-8" stroke="#D0011B" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
|
||||
<path d="M277.5,101.645833 L277.5,85.3541667" id="Line-7" stroke="#D0011B" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
|
||||
<path d="M197.5,102.5 L277.5,102.5" id="Line-6" stroke="#D0011B" stroke-linecap="square" sketch:type="MSShapeGroup"></path>
|
||||
<text id="3" sketch:type="MSTextLayer" font-family="Consolas" font-size="20" font-weight="normal" fill="#D0011B">
|
||||
<tspan x="185" y="101">3</tspan>
|
||||
</text>
|
||||
<text id="class="my"" sketch:type="MSTextLayer" font-family="Consolas" font-size="20" font-weight="normal" fill="#417505">
|
||||
<tspan x="185" y="119">class="my"</tspan>
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.9 KiB |
Loading…
Add table
Add a link
Reference in a new issue