当前位置:  开发笔记 > 编程语言 > 正文

如何在JavaScript正则表达式中访问匹配的组?

如何解决《如何在JavaScript正则表达式中访问匹配的组?》经验,为你挑选了13个好方法。

我想使用正则表达式匹配字符串的一部分,然后访问该带括号的子字符串:

var myString = "something format_abc"; // I want "abc"

var arr = /(?:^|\s)format_(.*?)(?:\s|$)/.exec(myString);

console.log(arr);     // Prints: [" format_abc", "abc"] .. so far so good.
console.log(arr[1]);  // Prints: undefined  (???)
console.log(arr[0]);  // Prints: format_undefined (!!!)

我究竟做错了什么?


我发现有什么不对上述正则表达式代码:实际的字符串,我反对是这样的测试:

"date format_%A"

报告"%A"未定义似乎是一种非常奇怪的行为,但它与此问题没有直接关系,所以我开了一个新的,为什么匹配的子字符串在JavaScript中返回"undefined"?.


问题是console.log它的参数就像一个printf语句,因为我正在记录的字符串("%A")有一个特殊的值,它试图找到下一个参数的值.



1> CMS..:

您可以像这样访问捕获组:

var myString = "something format_abc";
var myRegexp = /(?:^|\s)format_(.*?)(?:\s|$)/g;
var match = myRegexp.exec(myString);
console.log(match[1]); // abc


2> Mathias Byne..:

这是一种方法,您可以使用它来获得每个匹配的第n个捕获组:

function getMatches(string, regex, index) {
  index || (index = 1); // default to the first capturing group
  var matches = [];
  var match;
  while (match = regex.exec(string)) {
    matches.push(match[index]);
  }
  return matches;
}


// Example :
var myString = 'something format_abc something format_def something format_ghi';
var myRegEx = /(?:^|\s)format_(.*?)(?:\s|$)/g;

// Get an array containing the first capturing group for every match
var matches = getMatches(myString, myRegEx, 1);

// Log results
document.write(matches.length + ' matches found: ' + JSON.stringify(matches))
console.log(matches);


3> PhiLho..:

var myString = "something format_abc";
var arr = myString.match(/\bformat_(.*?)\b/);
console.log(arr[0] + " " + arr[1]);


4> 小智..:

关于上面的多匹配括号示例,我在找不到我想要的内容之后在这里寻找答案:

var matches = mystring.match(/(?:neededToMatchButNotWantedInResult)(matchWanted)/igm);

在看了上面带有while和.push()的稍微复杂的函数调用之后,我突然意识到问题可以用mystring.replace()代替非常优雅(替换不是重点,甚至没有完成,CLEAN,第二个参数的内置递归函数调用选项是!):

var yourstring = 'something format_abc something format_def something format_ghi';

var matches = [];
yourstring.replace(/format_([^\s]+)/igm, function(m, p1){ matches.push(p1); } );

在此之后,我认为我不会再使用.match()了.



5> Sebastien H...:

最后但并非最不重要的是,我发现一行代码对我来说很好(JS ES6):

let reg = /#([\S]+)/igm; // Get hashtags.
let string = 'mi alegría es total! ?\n#fiestasdefindeaño #PadreHijo #buenosmomentos #france #paris';

let matches = (string.match(reg) || []).map(e => e.replace(reg, '$1'));
console.log(matches);


6> Daniel Hallg..:

本答案中使用的术语:

匹配表示对您的字符串运行RegEx模式的结果,如下所示:someString.match(regexPattern).

匹配模式表示输入字符串的所有匹配部分,它们都位于匹配数组内.这些都是输入字符串中模式的所有实例.

匹配组表示要捕获的所有组,在RegEx模式中定义.(括号内的模式,如下:/format_(.*?)/g,哪里(.*?)是匹配的组.)这些模式位于匹配的模式中.

描述

要访问匹配的组,在每个匹配的模式中,您需要一个函数或类似的东西来迭代匹配.正如许多其他答案所示,有很多方法可以做到这一点.大多数其他答案使用while循环来迭代所有匹配的模式,但我想我们都知道这种方法的潜在危险.有必要匹配一个new RegExp()而不仅仅是模式本身,只在评论中提到.这是因为该.exec()方法的行为类似于生成器函数 - 它在每次匹配时停止,但.lastIndex在下次.exec()调用时保持其继续.

代码示例

下面是一个函数的一个例子searchString,它返回一个Array所有的匹配的模式,其中每一个match是一个Array与所有的含有匹配组.我没有使用while循环,而是提供了使用Array.prototype.map()函数和更for高效的方法的示例- 使用plain -loop.

简洁版本(更少的代码,更多的语法糖)

这些性能较差,因为它们基本上实现了forEach-loop而不是更快的for-loop.

// Concise ES6/ES2015 syntax
const searchString = 
    (string, pattern) => 
        string
        .match(new RegExp(pattern.source, pattern.flags))
        .map(match => 
            new RegExp(pattern.source, pattern.flags)
            .exec(match));

// Or if you will, with ES5 syntax
function searchString(string, pattern) {
    return string
        .match(new RegExp(pattern.source, pattern.flags))
        .map(match =>
            new RegExp(pattern.source, pattern.flags)
            .exec(match));
}

let string = "something format_abc",
    pattern = /(?:^|\s)format_(.*?)(?:\s|$)/;

let result = searchString(string, pattern);
// [[" format_abc", "abc"], null]
// The trailing `null` disappears if you add the `global` flag

高性能版本(更多代码,更少的语法糖)

// Performant ES6/ES2015 syntax
const searchString = (string, pattern) => {
    let result = [];

    const matches = string.match(new RegExp(pattern.source, pattern.flags));

    for (let i = 0; i < matches.length; i++) {
        result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i]));
    }

    return result;
};

// Same thing, but with ES5 syntax
function searchString(string, pattern) {
    var result = [];

    var matches = string.match(new RegExp(pattern.source, pattern.flags));

    for (var i = 0; i < matches.length; i++) {
        result.push(new RegExp(pattern.source, pattern.flags).exec(matches[i]));
    }

    return result;
}

let string = "something format_abc",
    pattern = /(?:^|\s)format_(.*?)(?:\s|$)/;

let result = searchString(string, pattern);
// [[" format_abc", "abc"], null]
// The trailing `null` disappears if you add the `global` flag

我还没有将这些替代方法与之前在其他答案中提到的方法进行比较,但我怀疑这种方法的性能较差,而且其他方法的安全性较低.



7> Jonathan Lon..:

你的语法可能不是最好的.FF/Gecko将RegExp定义为Function的扩展.
(FF2竟然typeof(/pattern/) == 'function')

这似乎是特定于FF - IE,Opera和Chrome都为它抛出异常.

相反,使用其他人先前提到的方法:RegExp#execString#match.
他们提供相同的结果:

var regex = /(?:^|\s)format_(.*?)(?:\s|$)/;
var input = "something format_abc";

regex(input);        //=> [" format_abc", "abc"]
regex.exec(input);   //=> [" format_abc", "abc"]
input.match(regex);  //=> [" format_abc", "abc"]



8> Andre Carnei..:

无需调用该exec方法!您可以直接在字符串上使用"match"方法.只是不要忘记括号.

var str = "This is cool";
var matches = str.match(/(This is)( cool)$/);
console.log( JSON.stringify(matches) ); // will print ["This is cool","This is"," cool"] or something like that...

位置0有一个包含所有结果的字符串.位置1具有由括号表示的第一个匹配,位置2具有在括号中隔离的第二个匹配.嵌套括号很棘手,所以要小心!


如果没有全局标志,则返回所有匹配项,只有它才能获得一个大标记,所以请注意这一点.
这有效并且感觉更自然。

9> Wiktor Strib..:

String#matchAll (see the Stage 3 Draft / December 7, 2018 proposal), simplifies acccess to all groups in the match object (mind that Group 0 is the whole match, while further groups correspond to the capturing groups in the pattern):

With matchAll available, you can avoid the while loop and exec with /g... Instead, by using matchAll, you get back an iterator which you can use with the more convenient for...of, array spread, or Array.from() constructs

This method yields a similar output to Regex.Matches in C#, re.finditer in Python, preg_match_all in PHP.

See a JS demo (tested in Google Chrome 73.0.3683.67 (official build), beta (64-bit)):

var myString = "key1:value1, key2-value2!!@key3=value3";
var matches = myString.matchAll(/(\w+)[:=-](\w+)/g);
console.log([...matches]); // All match with capturing group values


10> Nabil Kadimi..:

只有在您有一对括号时才能使用的单线程:

while ( ( match = myRegex.exec( myStr ) ) && matches.push( match[1] ) ) {};


为什么不`while(match = myRegex.exec(myStr))matches.push(match [1])`

11> eyelidlessne..:

使用你的代码:

console.log(arr[1]);  // prints: abc
console.log(arr[0]);  // prints:  format_abc

编辑:Safari 3,如果重要的话.



12> 小智..:

function getMatches(string, regex, index) {
  index || (index = 1); // default to the first capturing group
  var matches = [];
  var match;
  while (match = regex.exec(string)) {
    matches.push(match[index]);
  }
  return matches;
}


// Example :
var myString = 'Rs.200 is Debited to A/c ...2031 on 02-12-14 20:05:49 (Clear Bal Rs.66248.77) AT ATM. TollFree 1800223344 18001024455 (6am-10pm)';
var myRegEx = /clear bal.+?(\d+\.?\d{2})/gi;

// Get an array containing the first capturing group for every match
var matches = getMatches(myString, myRegEx, 1);

// Log results
document.write(matches.length + ' matches found: ' + JSON.stringify(matches))
console.log(matches);


13> 小智..:

使用es2018,您现在可以String.match()使用命名组,使您的正则表达式更加明确地说明其尝试执行的操作。

const url =
  '/sf/ask/17360801/?some=parameter';
const regex = /(?https?):\/\/(?[\w-\.]*)\/(?[\w-\./]+)\??(?.*?)?$/;
const { groups: segments } = url.match(regex);
console.log(segments);

你会得到像

{协议:“ https”,主机名:“ stackoverflow.com”,路径名:“ questions / 432493 / how-do-you-access-the-matched-groups-in-javascript-regular-expression”,查询字符串:“ some = parameter“}

推荐阅读
雨天是最美
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有