据我所知,JavaScript中没有命名的捕获组。获得类似功能的替代方法是什么?


当前回答

在ES6中,你可以使用数组解构来捕获你的组:

let text = '27 months';
let regex = /(\d+)\s*(days?|months?|years?)/;
let [, count, unit] = regex.exec(text) || [];

// count === '27'
// unit === 'months'

注意:

最后一个let中的第一个逗号跳过结果数组的第一个值,即整个匹配的字符串 .exec()后的||[]将在没有匹配时防止析构错误(因为.exec()将返回null)

其他回答

没有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"
}

有一个名为-regexp的node.js库,你可以在你的node.js项目中使用它(在浏览器中通过使用browserify或其他打包脚本打包该库)。但是,该库不能用于包含未命名捕获组的正则表达式。

如果在正则表达式中计算开头捕获花括号,则可以在正则表达式中的命名捕获组和编号捕获组之间创建映射,并且可以自由混合和匹配。在使用正则表达式之前,只需删除组名。我写了三个函数来证明这一点。请看这个要点:https://gist.github.com/gbirke/2cc2370135b665eee3ef

在ES6中,你可以使用数组解构来捕获你的组:

let text = '27 months';
let regex = /(\d+)\s*(days?|months?|years?)/;
let [, count, unit] = regex.exec(text) || [];

// count === '27'
// unit === 'months'

注意:

最后一个let中的第一个逗号跳过结果数组的第一个值,即整个匹配的字符串 .exec()后的||[]将在没有匹配时防止析构错误(因为.exec()将返回null)

更新:它终于成为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';

你可以使用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.