从括号中的字符串中提取部分

Extract parts from bracketed string

有一个字符串,其中部分标记为w/brackets:

abc(de)f(uv)xyz

如何将其拆分成如下部分:

abc | false
de | true
f | false
uv | true
xyz | false

其中true代表有括号的部分,false代表没有括号的部分。

N.B. 括号仅用于标记目的。嵌套的、不成对的括号和其他复杂的场景是不可能的。

正则表达式

鉴于括号序列保证有效且不包含嵌套序列,我们可以使正则表达式非常简单:

\(?([^()]+)\)?

  1. \(? - 可选择接受左括号
  2. ([^()]+)- 捕获任何不是左括号或右括号的内容
  3. \)? - 可选择接受右括号

代码

执行正则表达式

一旦我们执行了正则表达式 (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'))