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



我是正则表达式的新手,我不知道如何通过谷歌搜索来让它工作。我认为我的部分问题可能是我在搜索词中措辞问题时遇到问题。

这是我的问题:

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

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

我想选择包含"绿色"一词的括号的全部内容,并且只选择那些括号。也就是说,我想返回"薄荷(浅色(绿色裤子"和"森林(深色((染色(绿色衬衫">,而不是">沙发","桌子"或任何胡言乱语。

到目前为止我尝试过:

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

  • /(.*green.*/)似乎返回了整个文件。

  • 谷歌
  • 搜索问题:从我在这里和谷歌上找到的页面来看,我想要的是一个回溯,一个JavaScript不支持的正则表达式功能。不幸的是,我正在用JS工作,所以我需要一种方法来完成这项工作。

编辑:我刚刚意识到我想要输出的文本包含的括号比我最初意识到的要多,并编辑了我的示例以反映这一点。

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

您的值将位于捕获组 1 中。

(([^)]+bgreenb[^)]+))

解释

  • (匹配左括号
  • ([^)]+使用否定字符类匹配不)
  • bgreenb使用单词边界匹配单词绿色,以确保它不是较大匹配的一部分
  • [^)]+匹配一次或多次,不是)
  • )关闭捕获组
  • )匹配(

const regex = /(([^)]+bgreenb[^)]+))/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]);
}

编辑

要匹配green之前的平衡括号,您可以匹配一次或多次不右括号,或者使用非捕获组(?:和交替(?:[^)]+|([^)]+)匹配平衡括号:

(((?:[^)]+|([^)]+))*bgreenb[^)]+))

const regex = /(((?:[^)]+|([^)]+))*bgreenb[^)]+))/g;
const str = `OSDfhosjdjakjdnvkjndkfvjelkrjejrijrvrvrjvnkrjvnkn(mint (light) green pants)shdbfhsbdhfbsjd(couch)hvbjshdbvjhsbdfbjs(forest (dark) (stained) green shirt) sjdfjsdhfjshkdfjskdjfksjdfhfskdjf(table)`;
let m;
while ((m = regex.exec(str)) !== null) {
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
console.log(m[1]);
}

匹配平衡括号并不是一个容易的问题,用 JavaScript 更难解决。由于JS正则表达式引擎不允许递归。让我引用史蒂文·利维森(Steven Levithan(关于这个问题的话:

在这种情况下,问题在于您如何区分 最后一个右括号...和任何内括号。唯一的 最后一个右括号和内括号之间的区别是 它们在逻辑上是链接的(即,它们形成一个开/关对(。此逻辑无法通过简单的环顾断言来实现。

但是,他总结说,如果需要考虑已知的最大递归量,这是可能的。

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

((?:([^()]*?)|([^()]*bgreenb[^()]*)?|[^()])*?)

解释

  • (匹配左括号
  • (?:...)具有交替的非封盖组:
    • ([^()]*?)匹配内括号对,懒惰匹配任何不是()使用否定字符类,非贪婪
    • ([^()]*bgreenb[^()]*)?捕获第1组中带有单词边界的可选单词绿色,贪婪
    • [^()]"修改后的点":任何不是保持括号平衡()的东西
  • *?关闭非捕获组,匹配零次或更多次懒惰
  • )匹配(

演示

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

示例代码:

const regex = /((?:([^()]*?)|([^()]*bgreenb[^()]*)?|[^()])*?)/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 所示调整模式。

最新更新