如何找到围绕给定搜索词的括号之间的所有内容?

时间:2018-05-29 15:02:44

标签: javascript regex

我是正则表达式的新手,我无法通过Google搜索来弄清楚如何让它工作。我认为我的部分问题可能是我在搜索字词中无法用语言表达问题。

这是我的问题:

我有一个看起来像这样的字符串:

OSDfhosjdjakjdnvkjndkfvjelkrjejrijrvrvrjvnkrjvnkn(mint (light) green pants)shdbfhsbdhfbsjd(couch)hvbjshdbvjhsbdfbjs(forest (dark) (stained) green shirt) sjdfjsdhfjshkdfjskdjfksjdfhfskdjf(table)

我想选择包含单词" green,"的括号的全部内容。并且那些括号。也就是说,我想回归"薄荷(浅色)绿色裤子" "森林(深色)(染色)绿色衬衫"但"沙发","表"或任何乱码。

到目前为止我尝试过的事情:

  • /(.*?green.*?/)似乎返回了一个几乎任意的文本块围绕" green"以/开始和结束,这让我觉得我搞砸了以某种方式逃避括号。

  • /(.*green.*/)似乎会返回整个文档。

  • Google搜索问题: 似乎来自我在这里和Google上发现的页面,我想要的是一个外观,一个正则表达式功能JavaScript不支持。不幸的是,我在JS工作,所以我需要一种方法来完成这项工作。

编辑:我刚刚意识到我要输出的文字包含的句子比我最初想象的要多,并编辑了我的例子来反映这一点。

2 个答案:

答案 0 :(得分:4)

您可以使用捕获组,而不是前瞻。首先匹配左括号\(,然后在捕获组(中匹配全部,直到右括号\)

您的值将在捕获第1组。

\(([^)]+\bgreen\b[^)]+)\)

<强>解释

  • \(匹配左括号
  • ([^)]+使用否定的character class
  • 匹配)
  • \bgreen\b使用字边界匹配单词green以确保它不是更大匹配的一部分
  • [^)]+匹配一次或多次而非)
  • )关闭捕获组
  • \)匹配)

&#13;
&#13;
const regex = /\(([^)]+\bgreen\b[^)]+)\)/g;
const str = `OSDfhosjdjakjdnvkjndkfvjelkrjejrijrvrvrjvnkrjvnkn(mint green pants)shdbfhsbdhfbsjd(couch)hvbjshdbvjhsbdfbjs(forest green shirt) sjdfjsdhfjshkdfjskdjfksjdfhfskdjf(table)`;
let m;
while ((m = regex.exec(str)) !== null) {
  if (m.index === regex.lastIndex) {
    regex.lastIndex++;
  }
  console.log(m[1]);
}
&#13;
&#13;
&#13;

修改

要匹配green之前的平衡括号,您可以匹配不是右括号一次或多次,或使用非捕获组(?:alternation {{1匹配平衡括号}}:

\(((?:[^\)]+|\([^)]+\))*\bgreen\b[^)]+)\)

&#13;
&#13;
(?:[^\)]+|\([^)]+\)
&#13;
&#13;
&#13;

答案 1 :(得分:1)

匹配平衡括号不是一个简单的问题,使用JavaScript更难解决。由于JS正则表达式引擎不允许递归。让我引用Steven Levithan来解决这个问题:

  

在这种情况下,问题在于你如何区分   最后一个关闭括号...和任何内括号。唯一的   最后一个右括号和内括号之间的差异是   它们在逻辑上是链接的(即,它们形成一对开/关对)。   这种逻辑不可能通过简单的外观断言来实现。

然而,他总结说,如果有一个已知的最大递归量需要考虑,那就有可能。

这是一个不使用任何高级正则表达式功能的解决方案,并且可以与vanilla JavaScript一起使用。

\((?:\([^()]*?\)|([^()]*\bgreen\b[^()]*)?|[^()])*?\)

<强>解释

  • \(匹配左括号
  • (?:...) 替换的非capputring组:
    • \([^()]*?\)匹配内部括号对,懒惰匹配任何不是()的东西,使用否定的character class,非贪婪
    • ([^()]*\bgreen\b[^()]*)?使用第1组中的字边界捕获可选字绿色,贪婪
    • [^()]“修改过的点”:任何不是()以保持括号均衡的内容
  • *?关闭非捕获组,匹配零次或多次懒惰
  • \)匹配)

Demo

我使用额外的捕获组来满足给定搜索词的要求;如果没有$ 1则完全匹配是垃圾:

示例代码:

const regex = /\((?:\([^()]*?\)|([^()]*\bgreen\b[^()]*)?|[^()])*?\)/gm;
const str = `OSDfhosjdjakjdnvkjndkfvjelkrjejrijrvrvrjvnkrjvnkn(mint (light) green pants)shdbfhsbdhfbsjd(couch)hvbjshdbvjhsbdfbjs(forest (dark) (stained) green shirt) sjdfjsdhfjshkd(fjskdjfksjdfhfskdjf(green table) (green)`;
let m;

while ((m = regex.exec(str)) !== null) {
    // This is necessary to avoid infinite loops with zero-width matches
    if (m.index === regex.lastIndex) {
        regex.lastIndex++;
    }
    
    // The result can be accessed through the `m`-variable.
    m.forEach((match, groupIndex) => {
      if(match && groupIndex === 1)
        console.log(`Found ${m[0]}`);
    });
}

警告,这仅适用于:

  • 大括号实际上是平衡的,
  • 并且支撑嵌套的级别不超过一个。 如果需要更多级别,请调整模式,如Steven所示。