Група захоплення: (...)
Група захоплення групує підпатерн, даючи змогу застосувати до всієї групи квантор, або застосувати в ній диз'юнкції. Вона запам'ятовує інформацію про збіг з підпатерном, щоб на цей збіг можна було пізніше посилатися за допомогою зворотного посилання та звертатися до цієї інформації за допомогою об'єкта результатів збігу.
Якщо результат збігу з підпатерном – не потрібен, слід натомість використовувати незахоплювальну групу, що покращує продуктивність та уникне неприємностей при рефакторингу.
Синтаксис
(патерн)
Параметри
patternПатерн, що складається з будь-чого, що можна використовувати в літералі регулярного виразу, включно з диз'юнкцією.
Опис
Група захоплення діє подібно до оператора групування в JavaScript-виразах, даючи змогу використовувати підпатерн як єдиний атом.
Групи захоплення нумеруються за порядком їхніх стартових дужок. Перша група захоплення отримує номер 1, друга – 2, і так далі. Іменовані групи захоплення також є групами захоплення та нумеруються разом з іншими (безіменними) групами захоплення. Інформацію про збіг з групою захоплення можна отримати за допомогою:
- Поверненого значення (котре є масивом) з методу
RegExp.prototype.exec(),String.prototype.match()абоString.prototype.matchAll() - Параметрів
pNфункції зворотного викликуreplacementметодівString.prototype.replace()іString.prototype.replaceAll() - Зворотних посилань у межах того самого патерну
Примітка: Навіть у результівному масиві методу
exec()групи захоплення доступні за числами1,2тощо, адже елемент0– це ввесь збіг.\0– це не зворотне посилання, а послідовність екранування для символу NUL.
Групи захоплення у вихідному коді регулярного виразу відповідають своїм результатам один до одного. Якщо група захоплення не отримала збігу (наприклад, коли вона належить до варіанту диз'юнкції, що не отримав збігу), то відповідним результатом є undefined.
/(ab)|(cd)/.exec("cd"); // ['cd', undefined, 'cd']
Групи захоплення можуть бути квантовані. У такому випадку інформація про збіг, що відповідає такій групі, – це останній збіг групи.
/([ab])+/.exec("abc"); // ['ab', 'b']; через те, що "b" стоїть після "a", цей результат відкидає попередній
Групи захоплення можуть вживатися у твердженнях визирання й озирання. У зв'язку з тим, що твердження озирання шукають збіг зі своїми атомами позаду справа наліво, то остаточний збіг, що відповідає такій групі, це той, що стоїть з лівого боку рядка. А проте, індекси груп збігів все одно відповідатимуть їхнім відносним розташуванням у вихідному коді регулярного виразу.
/c(?=(ab))/.exec("cab"); // ['c', 'ab']
/(?<=(a)(b))c/.exec("abc"); // ['c', 'a', 'b']
/(?<=([ab])+)c/.exec("abc"); // ['c', 'a']; тому що "a" помічено озиранням після того, як озиранням помічено "b"
Групи захоплення можуть мати вкладеність, у випадку чого зовнішня група нумерується першою, потім – внутрішня група, тому що нумерація відповідає стартовим дужкам. Якщо вкладена група повторюється за допомогою квантора, то кожного разу, коли з нею трапляється збіг, результати підгруп перезаписуються, іноді – значенням undefined.
/((a+)?(b+)?(c))*/.exec("aacbbbcac"); // ['aacbbbcac', 'ac', 'a', undefined, 'c']
У прикладі вище зовнішня група збігається тричі:
- Збігається з
"aac", з підгрупами"aa",undefinedі"c". - Збігається з
"bbbc", з підгрупамиundefined,"bbb"і"c". - Збігається з
"ac", з підгрупами"a",undefinedі"c".
Результат "bbb" з другого збігу – не зберігається, тому що третій збіг відкидає його своїм значенням undefined.
Початковий та кінцевий індекси кожної групи захоплення в вихідному рядку можна отримати за допомогою позначки d. Це створює додаткову властивість indices у масиві, поверненому з exec().
Іще можна задати назву групи захоплення, що допомагає уникнути пасток, пов'язаних із позиціями груп та індексами. Докладніше про це – читайте Іменовані групи захоплення.
Дужки в різних записах регулярних виразів мають інші значення. Наприклад, також вони охоплюють твердження визирання й озирання. Через те, що всі такі записи починаються з ?, а ? - це квантор, котрий зазвичай не стоїть зразу після (, це не призводить до неоднозначностей.
Приклади
Пошук дати
Наступний приклад шукає дату в форматі YYYY-MM-DD:
function parseDate(input) {
const parts = /^(\d{4})-(\d{2})-(\d{2})$/.exec(input);
if (!parts) {
return null;
}
return parts.map((p) => parseInt(p, 10));
}
parseDate("2019-01-01"); // [2019, 1, 1]
parseDate("2019-06-19"); // [2019, 6, 19]
Парування лапок
Наступна функція шукає в рядку патерни title='xxx' і title="xxx". Аби пересвідчитися, що лапки збігаються, використовується зворотне посилання, аби звернутися до першої лапки. Звертання до другої групи захоплення ([2]) повертає рядок між лапками, що збігаються:
function parseTitle(metastring) {
return metastring.match(/title=(["'])(.*?)\1/)[2];
}
parseTitle('title="foo"'); // 'foo'
parseTitle("title='foo' lang='en'"); // 'foo'
parseTitle('title="Named capturing groups\' advantages"'); // "Named capturing groups' advantages"