Именованные группы и оператор OR в JS - PullRequest
0 голосов
/ 21 февраля 2019

Я пытаюсь сопоставить строки, такие как 2h30m, 24h, 1d20h30s и извлечь каждый сегмент с именованной группой.Звучит просто и выполнимо, и если вы используете PCRE с регулярным выражением, подобным следующему:

^(((?<h>[0-9]+)h)|((?<m>[0-9]+)m))+$

Полный пример на regexr , вы можете переключаться между PCRE и движком Javascript в правом верхнем углу.угол.

Дело в том, что он не работает в JavaScript, и я не могу понять, почему.Я предполагаю, что это как-то связано с взаимодействием между оператором OR и именованными группами, поскольку при использовании javascript он возвращает только одну из названных групп

. Вопрос в том, почему?и если есть какой-нибудь способ заставить это работать в javascript

1 Ответ

0 голосов
/ 21 февраля 2019

Кажется, | следует заменить на ? для захвата нескольких групп подряд (при | может быть захвачена только одна последняя группа в строке).И нам нужно добавить непустое утверждение, чтобы предотвратить совпадение пустой строки.Кроме того, стоит вставить немного ?:, чтобы некоторые группы не захватывались.

'use strict';

const str = `
2h30m
24h
1d20h30s
`;

const re = /^(?=.+)(?:(?:(?<d>[0-9]+)d)?(?:(?<h>[0-9]+)h)?(?:(?<m>[0-9]+)m)?(?:(?<s>[0-9]+)s)?(?:(?<ms>[0-9]+)ms)?)+$/gm;

let result;

while (result = re.exec(str)) console.log(result.groups);

Если ваш Node.js (или браузер) поддерживает новый метод matchAll(), это также может быть достигнуто следующим образом:

'use strict';

const str = `
2h30m
24h
1d20h30s
`;

const re = /^(?=.+)(?:(?:(?<d>[0-9]+)d)?(?:(?<h>[0-9]+)h)?(?:(?<m>[0-9]+)m)?(?:(?<s>[0-9]+)s)?(?:(?<ms>[0-9]+)ms)?)+$/gm;

console.log(Array.from(str.matchAll(re), ({ groups }) => groups));
...