我是正则表达式的新手,我不知道如何通过谷歌搜索来让它工作。我认为我的部分问题可能是我在搜索词中措辞问题时遇到问题。
这是我的问题:
我有一个看起来像这样的字符串:
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 所示调整模式。