Tim*_*ker 105
ECMAScript 2018将命名捕获组引入JavaScript正则表达式.
如果您需要支持旧版浏览器,您可以使用正常(编号)捕获组执行所有操作,您可以使用命名捕获组执行操作,您只需要跟踪数字 - 如果在您的捕获组的顺序中这可能很麻烦正则表达式的变化.
我能想到的命名捕获组只有两个"结构"优势:
在一些正则表达式中(.NET和JGSoft,据我所知),您可以在正则表达式中为不同的组使用相同的名称(有关这一事项的示例,请参阅此处).但是大多数正则表达式都不支持这种功能.
如果您需要在数字包围的情况下引用编号的捕获组,则可能会出现问题.假设您想要为数字添加零,因此要替换(\d)为$10.在JavaScript中,这将起作用(只要你的正则表达式中有少于10个捕获组),但Perl会认为你正在寻找反向引号10而不是数字1,然后是a 0.在Perl中,您可以${1}0在这种情况下使用.
除此之外,命名捕获组只是"语法糖".仅在您真正需要时才使用捕获组,并(?:...)在所有其他情况下使用非捕获组.
使用JavaScript的更大问题(在我看来)是它不支持详细的正则表达式,这将使可读,复杂的正则表达式的创建更容易.
Steve Levithan的XRegExp库解决了这些问题.
Mr.*_* TA 56
另一种可能的解决方案:创建一个包含组名和索引的对象.
var regex = new RegExp("(.*) (.*)");
var regexGroups = { FirstName: 1, LastName: 2 };
Run Code Online (Sandbox Code Playgroud)
然后,使用对象键来引用组:
var m = regex.exec("John Smith");
var f = m[regexGroups.FirstName];
Run Code Online (Sandbox Code Playgroud)
这使用正则表达式的结果提高了代码的可读性/质量,但不提高了正则表达式本身的可读性.
fre*_*nte 56
在ES6中,您可以使用数组解构来捕获您的组:
let text = '27 months';
let regex = /(\d+)\s*(days?|months?|years?)/;
let [, count, unit] = regex.exec(text) || [];
// count === '27'
// unit === 'months'
Run Code Online (Sandbox Code Playgroud)
注意:
let跳过结果数组的第一个值,即整个匹配的字符串|| []after .exec()会阻止解构错误(因为.exec()会返回null)For*_*vin 19
更新:它最终成为JavaScript(ECMAScript 2018)!
命名捕获组可以很快进入JavaScript.
它的提议已经在第3阶段.
(?<name>...)对于任何标识符名称,可以使用语法在角括号内为捕获组指定名称.然后可以将日期的正则表达式写为/(?<year>\d{4})-(?<month>\d{2})-(?<day>\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';
Run Code Online (Sandbox Code Playgroud)
命名捕获的组提供了一件事:与复杂的正则表达式混淆较少.
这真的取决于你的用例,但也许漂亮打印你的正则表达式可以帮助.
或者您可以尝试定义常量以引用捕获的组.
然后,评论可能也有助于向其他人展示您的代码,以及您所做的事情.
对于其他人,我必须同意蒂姆的回答.
正如Tim Pietzcker所说,ECMAScript 2018 将命名捕获组引入 JavaScript 正则表达式。但是我在上面的答案中没有找到的是如何在正则表达式本身中使用命名的捕获组。
您可以使用命名捕获组语法:\k<name>。例如
var regexObj = /(?<year>\d{4})-(?<day>\d{2})-(?<month>\d{2}) year is \k<year>/
Run Code Online (Sandbox Code Playgroud)
正如Forivin所说,您可以在对象结果中使用捕获的组,如下所示:
let result = regexObj.exec('2019-28-06 year is 2019');
// result.groups.year === '2019';
// result.groups.month === '06';
// result.groups.day === '28';
Run Code Online (Sandbox Code Playgroud)
var regexObj = /(?<year>\d{4})-(?<day>\d{2})-(?<month>\d{2}) year is \k<year>/
Run Code Online (Sandbox Code Playgroud)
let result = regexObj.exec('2019-28-06 year is 2019');
// result.groups.year === '2019';
// result.groups.month === '06';
// result.groups.day === '28';
Run Code Online (Sandbox Code Playgroud)
var regexObj = /(?<year>\d{4})-(?<day>\d{2})-(?<month>\d{2}) year is \k<year>/mgi;
function check(){
var inp = document.getElementById("tinput").value;
let result = regexObj.exec(inp);
document.getElementById("year").innerHTML = result.groups.year;
document.getElementById("month").innerHTML = result.groups.month;
document.getElementById("day").innerHTML = result.groups.day;
}Run Code Online (Sandbox Code Playgroud)
有一个名为named-regexp的node.js库可以在node.js项目中使用(在浏览器中使用browserify或其他打包脚本打包库).但是,该库不能与包含非命名捕获组的正则表达式一起使用.
如果计算正则表达式中的开始捕获括号,则可以在命名捕获组和正则表达式中编号的捕获组之间创建映射,并可以自由混合和匹配.您只需在使用正则表达式之前删除组名称.我写了三个函数来证明这一点.看到这个要点:https://gist.github.com/gbirke/2cc2370135b665eee3ef