Регулярное выражение
Учитывая, что скобочная последовательность гарантированно действительна и не содержит вложенных последовательностей, мы можем сохранить регулярное выражение довольно простым:
\(?([^()]+)\)?
\(?
- опционально принимайте открывающую скобку ([^()]+)
- захватывайте все, что не является открывающей или закрывающей скобкой \)?
- дополнительно принимайте закрывающую скобку
Код
Выполнение регулярного выражения
Как только мы выполним регулярное выражение (execAll(pattern, text)
), мы получим
const matches = execAll(pattern, text)
[
['abc', 'abc'],
['(de)', 'de'],
['f' , 'f' ]
['(uv)', 'uv'],
['xyz', 'xyz']
]
в скобках против без скобок
Индекс 0
каждой записи соответствует тексту, а индекс 1
- захваченная группа.
Просмотр первого символа индекса 0
говорит нам, является ли это группа или не:
matches[0][0] === '(' // false
matches[1][0] === '(' // true
Приведение в правильном порядке
Мы хотим, чтобы сначала был текст, а затем логическое значение:
matches.map(([bracket, group]) => [group, bracket[0]==='('])
[
['abc', false],
['de' , true ],
['f' , false]
['uv' , true ],
['xyz', false]
]
Готово!
Решение
const execAll = (pattern, str) => {
const result=[]
let match
while((match = pattern.exec(str))) {
result.push(match)
}
return result
}
const extractGroups = text => {
const pattern = /\(?([^()]+)\)?/g
const matches = execAll(pattern, text)
return matches
.map(([bracket, group]) => [group, bracket[0]==='('])
}
console.log(extractGroups('abc(de)f(uv)xyz'))