据我所知,JavaScript中没有命名的捕获组。获得类似功能的替代方法是什么?
当前回答
你可以使用XRegExp,一个扩展的、可扩展的、跨浏览器的正则表达式实现,包括对额外语法、标志和方法的支持:
Adds new regex and replacement text syntax, including comprehensive support for named capture. Adds two new regex flags: s, to make dot match all characters (aka dotall or singleline mode), and x, for free-spacing and comments (aka extended mode). Provides a suite of functions and methods that make complex regex processing a breeze. Automagically fixes the most commonly encountered cross-browser inconsistencies in regex behavior and syntax. Lets you easily create and use plugins that add new syntax and flags to XRegExp's regular expression language.
其他回答
ECMAScript 2018在JavaScript正则表达式中引入了命名捕获组。
例子:
const auth = 'Bearer AUTHORIZATION_TOKEN'
const { groups: { token } } = /Bearer (?<token>[^ $]*)/.exec(auth)
console.log(token) // "AUTHORIZATION_TOKEN"
如果您需要支持旧的浏览器,您可以使用普通的(编号的)捕获组来完成您可以使用命名捕获组来完成的所有事情,您只需要跟踪数字—如果正则表达式中捕获组的顺序发生了变化,这可能会很麻烦。
我能想到的命名捕获组只有两个“结构性”优势:
In some regex flavors (.NET and JGSoft, as far as I know), you can use the same name for different groups in your regex (see here for an example where this matters). But most regex flavors do not support this functionality anyway. If you need to refer to numbered capturing groups in a situation where they are surrounded by digits, you can get a problem. Let's say you want to add a zero to a digit and therefore want to replace (\d) with $10. In JavaScript, this will work (as long as you have fewer than 10 capturing group in your regex), but Perl will think you're looking for backreference number 10 instead of number 1, followed by a 0. In Perl, you can use ${1}0 in this case.
除此之外,命名捕获组只是“语法糖”。只有在真正需要时才使用捕获组,在所有其他情况下使用非捕获组(?:…)会有所帮助。
JavaScript最大的问题(在我看来)是它不支持冗长的正则表达式,这使得创建可读的复杂正则表达式变得容易得多。
Steve Levithan的XRegExp库解决了这些问题。
为捕获的组命名有一个好处:减少与复杂正则表达式的混淆。
这真的取决于你的用例,但也许漂亮地打印你的正则表达式会有所帮助。
或者您可以尝试定义常量来引用您捕获的组。
注释可能还有助于向阅读您代码的其他人展示您所做的工作。
至于其他的,我必须同意蒂姆的回答。
你可以使用XRegExp,一个扩展的、可扩展的、跨浏览器的正则表达式实现,包括对额外语法、标志和方法的支持:
Adds new regex and replacement text syntax, including comprehensive support for named capture. Adds two new regex flags: s, to make dot match all characters (aka dotall or singleline mode), and x, for free-spacing and comments (aka extended mode). Provides a suite of functions and methods that make complex regex processing a breeze. Automagically fixes the most commonly encountered cross-browser inconsistencies in regex behavior and syntax. Lets you easily create and use plugins that add new syntax and flags to XRegExp's regular expression language.
更新:它终于成为JavaScript (ECMAScript 2018)!
命名捕获组很快就会出现在JavaScript中。 提案已经进入第三阶段。
捕获组可以使用(?<name>…)语法在尖括号内指定名称,用于 任何标识符名称。日期的正则表达式可以是 写成/(? <一> \ d{4})——(? <月> \ d{2})——(? <天> \ d {2}) / u。每个名称 应该是唯一的,并遵循ECMAScript IdentifierName的语法。
的groups属性中的属性可以访问命名组 正则表达式结果。对组的编号引用是 也创建了,就像未命名组一样。例如:
let re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
let result = re.exec('2015-01-02');
// result.groups.year === '2015';
// result.groups.month === '01';
// result.groups.day === '02';
// result[0] === '2015-01-02';
// result[1] === '2015';
// result[2] === '01';
// result[3] === '02';
没有ECMAScript 2018?
我的目标是使它的工作尽可能类似于我们所习惯的命名组。而在ECMAScript 2018中,你可以在组中放置?<groupname>来表示一个命名组,在我的旧javascript解决方案中,你可以在组中放置(?!=<groupname>)来做同样的事情。所以它是一组额外的括号和一个额外的!=。很接近!
我把它都包装成一个字符串原型函数
特性
适用于较旧的javascript 没有额外的代码 使用起来非常简单 Regex仍然有效 组是在正则表达式本身中记录的 组名可以有空格 返回带有结果的对象
指令
将(?!={groupname})放置在您想要命名的每个组中 记住,通过在组的开头放置?:来消除任何非捕获组()。这些不会被命名。
arrays.js
// @@pattern - includes injections of (?!={groupname}) for each group
// @@returns - an object with a property for each group having the group's match as the value
String.prototype.matchWithGroups = function (pattern) {
var matches = this.match(pattern);
return pattern
// get the pattern as a string
.toString()
// suss out the groups
.match(/<(.+?)>/g)
// remove the braces
.map(function(group) {
return group.match(/<(.+)>/)[1];
})
// create an object with a property for each group having the group's match as the value
.reduce(function(acc, curr, index, arr) {
acc[curr] = matches[index + 1];
return acc;
}, {});
};
使用
function testRegGroups() {
var s = '123 Main St';
var pattern = /((?!=<house number>)\d+)\s((?!=<street name>)\w+)\s((?!=<street type>)\w+)/;
var o = s.matchWithGroups(pattern); // {'house number':"123", 'street name':"Main", 'street type':"St"}
var j = JSON.stringify(o);
var housenum = o['house number']; // 123
}
o的结果
{
"house number": "123",
"street name": "Main",
"street type": "St"
}