JavaScript 正则表达式全局匹配组

Posted

技术标签:

【中文标题】JavaScript 正则表达式全局匹配组【英文标题】:JavaScript Regex Global Match Groups 【发布时间】:2013-11-23 16:28:30 【问题描述】:

更新:这个问题与this几乎重复

我确定我的问题的答案就在那里,但我找不到简洁的词语来表达它。我正在尝试使用 javascript 正则表达式执行以下操作:

var input = "'Warehouse','Local Release','Local Release DA'";
var regex = /'(.*?)'/g;

console.log(input.match(regex));

// Actual:
// ["'Warehouse'", "'Local Release'", "'Local Release DA'"]

// What I'm looking for (without the '):
// ["Warehouse", "Local Release", "Local Release DA"]

有没有一种干净的方法来使用 JavaScript 正则表达式来做到这一点?显然我可以自己去掉's,但我正在寻找正确的方法来使用正则表达式捕获全局匹配的分组。

【问题讨论】:

How do you access the matched groups in a javascript regex?的可能重复 是的,这绝对是重复的,我不知道如何搜索我的问题:/ 我是通过搜索[javascript] [regex] 全局捕获组找到的。 【参考方案1】:

要使用正则表达式执行此操作,您需要使用 .exec() 对其进行迭代,以获得多个匹配的组。带有 match 的 g 标志只会返回多个完整的匹配,而不是您想要的多个子匹配。这是使用.exec() 的一种方法。

var input = "'Warehouse','Local Release','Local Release DA'";
var regex = /'(.*?)'/g;

var matches, output = [];
while (matches = regex.exec(input)) 
    output.push(matches[1]);

// result is in output here

工作演示:http://jsfiddle.net/jfriend00/VSczR/


对字符串中的内容进行某些假设后,您也可以直接使用:

var input = "'Warehouse','Local Release','Local Release DA'";
var output = input.replace(/^'|'$/, "").split("','");

工作演示:http://jsfiddle.net/jfriend00/MFNm3/


注意:使用截至 2021 年的现代 Javascript 引擎,您可以使用 str.matchAll(regex) 并在一个函数调用中获取所有匹配项。

【讨论】:

添加了一个非正则表达式的方式也可以做到这一点。 我用这个正则表达式 /<img[^>]+?src=(?:(?:'([^']*)')|(?:"([^"]*)")|([^\s]*))/i 应用了这个循环,控制台不响应并且使用 1 个完整的 cpu 核心进行 chrome 处理 哦,我忘记了g 修饰符。现在好了 这将在 jslink 中失败.. 改为这样做 while ((matches = regex.exec(input)) !== null) @keithics - jslink 返回的不是null 到底是什么?这很奇怪。 .exec() 应该返回一个数组或 null 所以原始代码应该检测到不匹配就好了。【参考方案2】:

有一个名为 String.prototype.matchAll() 的 ECMAScript 提案可以满足您的需求。

【讨论】:

看来这已经得到很好的支持了!甜! 没错:caniuse.com/?search=String.prototype.matchAll【参考方案3】:

不是很通用的解决方案,因为 Javascript 不支持lookbehind,但是对于给定的输入,这个正则表达式应该可以工作:

m = input.match(/([^',]+)(?=')/g);
//=> ["Warehouse", "Local Release", "Local Release DA"]

【讨论】:

【参考方案4】:

String.prototype.matchAll 现在是 well supported in modern browsers 以及 Node.js. 这可以这样使用:

const matches = Array.from(myString.matchAll(/myRegEx/g)).map(match => match[1]);

注意传递的RegExp必须有全局标志,否则会抛出错误。

方便的是,当找不到匹配项时,这不会引发错误,因为 .matchAll 总是返回一个迭代器(而不是 .match() 返回 null)。


对于这个具体的例子:

var input = "'Warehouse','Local Release','Local Release DA'";
var regex = /'(.*?)'/g;

var matches = Array.from(input.matchAll(regex)).map(match => match[1]);
// [ "Warehouse", "Local Release", "Local Release DA" ]

【讨论】:

Array.from 接受 mapFn 作为第二个参数。所以还有可能是:Array.from(myString.matchAll(/myRegEx/g), m => m[1])。 MDN 在其 matchAll 文档中使用它作为示例,请参阅 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…【参考方案5】:

尝试input.replace(regex, "$1") 之类的方法来获取捕获组的结果。

【讨论】:

进入数组 - input.replace(regex, "$1").split(',') OP 想要数组中的结果。 我喜欢你的思路,假设内容中没有,s。 @Jondlm 可以做 - regex = /'(.*?)'(,?)/g;input.replace(regex, "$1$2$2").split(',,')【参考方案6】:

使用 es2020 你可以使用matchAll:

var input = "'Warehouse','Local Release','Local Release DA'";
var regex = /'(.*?)'/g;

const match_all = [...input.matchAll(regex)];

如果您使用的是打字稿,请不要忘记将其设置在tsconfig.json

"compilerOptions": 
    "lib": ["es2020.string"]

【讨论】:

【参考方案7】:

此正则表达式有效,但使用已定义的字符...

var input = "'Warehouse','Local Release','Local Release DA'";

var r =/'[\w\s]+'/gi;
console.log(input.match(regex));

【讨论】:

这会在结果中留下单引号,这不是 OP 想要的。【参考方案8】:

编辑:这在 javascript 中不起作用,但它在 java 中起作用。对不起。

是的,它被称为“向前看”“向后看”

(?<=').*?(?=')
(?=') 向前寻找 ' (?

测试一下here

【讨论】:

在javascript中没有后面的样子。 既然知道它在 Javascript 中不起作用,为什么还要写它呢?否则人们会用 Java 标签询问。乞丐的信仰…… JavaScript 中现在有look behind 这是一篇关于如何使用lookbehind和lookahed的文章:v8.dev/blog/regexp-lookbehind-assertions

以上是关于JavaScript 正则表达式全局匹配组的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript中使用正则表达式

JavaScript正则表达式修饰符

[JavaScript] js中全局标识正则表达式的lastIndex属性

在正则表达式(Javascript)中分隔捕获组[重复]

[javascript] 获取正则子表达式里的内容

JavaScript RegExp(正则表达式) 对象