# Скобочные группы
Часть шаблона может быть заключена в скобки (...)
. Такие выделенные части шаблона называют "скобочными выражениями" или "скобочными группами".
У такого выделения есть два эффекта:
(go)+
находит один или более повторяющихся 'go'
:
```js
//+ run
alert( 'Gogogo now!'.match(/(go)+/i ); // "Gogogo"
```
Без скобок, шаблон /go+/
означал бы g
, после которого идёт одна или более o
, например: goooo
. А скобки "группируют" (go)
вместе.
## Содержимое группы
Скобки нумеруются слева направо. Поисковой движок запоминает содержимое каждой скобки и позволяет обращаться к нему -- в шаблоне и строке замены и, конечно же, в результатах.
Например, найти HTML-тег можно шаблоном <.*?>
.
После поиска мы захотим что-то сделать с результатом. Для удобства заключим содержимое `<...>` в скобки: <(.*?)>
. Тогда оно будет доступно отдельно.
При поиске методом [String#match](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/String/match) в результирующем массиве будет сначала всё совпадение, а далее -- скобочные группы. В шаблоне <(.*?)>
скобочная группа только одна:
```js
//+ run
var str = '<h1>
, а закрывающий </h1>
не нашёл, поскольку без флага `/.../g` ищется только первое совпадение.
Для того, чтобы искать и с флагом `/.../g` и со скобочными группами, используется метод [RegExp#exec](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec):
```js
//+ run
var str = '<(.*?)>
, каждое -- массив из полного совпадения и скобочных групп (одна в данном случае).
## Вложенные группы
Скобки могут быть и вложенными. В этом случае нумерация также идёт слева направо.
Например, при поиске тега в <span class="my">
нас может интересовать:
a(z)?(c)?
. Он ищет `"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`.
А теперь более сложная ситуация, строка ack
:
```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`. Она постоянна. А вот для скобочной группы (z)?
в ней ничего нет, поэтому результат: `["ac", undefined, "c"]`.
## Исключение из запоминания через ?:
Бывает так, что скобки нужны, чтобы квантификатор правильно применился, а вот запоминать её в массиве не нужно.
Скобочную группу можно исключить из запоминаемых и нумеруемых, добавив в её начало ?:
.
Например, мы хотим найти (go)+
, но содержимое скобок (`go`) в отдельный элемент массива выделять не хотим.
Для этого нужно сразу после открывающей скобки поставить `?:`, то есть: (?:go)+
.
Например:
```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` и содержит только полное совпадение и результат (\w+)
. Это удобно в тех случаях, когда содержимое скобок нас не интересует.