RegEx to extract all matches from string using RegExp.exec

前端 未结 17 1137
-上瘾入骨i
-上瘾入骨i 2020-11-22 02:49

I\'m trying to parse the following kind of string:

[key:\"val\" key2:\"val2\"]

where there are arbitrary key:\"val\" pairs inside. I want t

相关标签:
17条回答
  • 2020-11-22 03:01

    Since ES9, there's now a simpler, better way of getting all the matches, together with information about the capture groups, and their index:

    const string = 'Mice like to dice rice';
    const regex = /.ice/gu;
    for(const match of string.matchAll(regex)) {
        console.log(match);
    }
    

    // ["mice", index: 0, input: "mice like to dice rice", groups: undefined]

    // ["dice", index: 13, input: "mice like to dice rice", groups: undefined]

    // ["rice", index: 18, input: "mice like to dice rice", groups: undefined]

    It is currently supported in Chrome, Firefox, Opera. Depending on when you read this, check this link to see its current support.

    0 讨论(0)
  • 2020-11-22 03:02

    If you have ES9

    (Meaning if your system: Chrome, Node.js, Firefox, etc supports Ecmascript 2019 or later)

    Use the new yourString.matchAll( /your-regex/ ).

    If you don't have ES9

    If you have an older system, here's a function for easy copy and pasting

    function findAll(regexPattern, sourceString) {
        let output = []
        let match
        // make sure the pattern has the global flag
        let regexPatternWithGlobal = RegExp(regexPattern,[...new Set("g"+regexPattern.flags)].join(""))
        while (match = regexPatternWithGlobal.exec(sourceString)) {
            // get rid of the string copy
            delete match.input
            // store the match data
            output.push(match)
        } 
        return output
    }
    

    example usage:

    console.log(   findAll(/blah/g,'blah1 blah2')   ) 
    

    outputs:

    [ [ 'blah', index: 0 ], [ 'blah', index: 6 ] ]
    
    0 讨论(0)
  • 2020-11-22 03:03

    Here is my answer:

    var str = '[me nombre es] : My name is. [Yo puedo] is the right word'; 
    
    var reg = /\[(.*?)\]/g;
    
    var a = str.match(reg);
    
    a = a.toString().replace(/[\[\]]/g, "").split(','));
    
    0 讨论(0)
  • 2020-11-22 03:05

    Here's a one line solution without a while loop.

    The order is preserved in the resulting list.

    The potential downsides are

    1. It clones the regex for every match.
    2. The result is in a different form than expected solutions. You'll need to process them one more time.
    let re = /\s*([^[:]+):\"([^"]+)"/g
    let str = '[description:"aoeu" uuid:"123sth"]'
    
    (str.match(re) || []).map(e => RegExp(re.source, re.flags).exec(e))
    
    
    [ [ 'description:"aoeu"',
        'description',
        'aoeu',
        index: 0,
        input: 'description:"aoeu"',
        groups: undefined ],
      [ ' uuid:"123sth"',
        'uuid',
        '123sth',
        index: 0,
        input: ' uuid:"123sth"',
        groups: undefined ] ]
    
    0 讨论(0)
  • 2020-11-22 03:08

    My guess is that if there would be edge cases such as extra or missing spaces, this expression with less boundaries might also be an option:

    ^\s*\[\s*([^\s\r\n:]+)\s*:\s*"([^"]*)"\s*([^\s\r\n:]+)\s*:\s*"([^"]*)"\s*\]\s*$
    

    If you wish to explore/simplify/modify the expression, it's been explained on the top right panel of regex101.com. If you'd like, you can also watch in this link, how it would match against some sample inputs.


    Test

    const regex = /^\s*\[\s*([^\s\r\n:]+)\s*:\s*"([^"]*)"\s*([^\s\r\n:]+)\s*:\s*"([^"]*)"\s*\]\s*$/gm;
    const str = `[description:"aoeu" uuid:"123sth"]
    [description : "aoeu" uuid: "123sth"]
    [ description : "aoeu" uuid: "123sth" ]
     [ description : "aoeu"   uuid : "123sth" ]
     [ description : "aoeu"uuid  : "123sth" ] `;
    let m;
    
    while ((m = regex.exec(str)) !== null) {
        // This is necessary to avoid infinite loops with zero-width matches
        if (m.index === regex.lastIndex) {
            regex.lastIndex++;
        }
        
        // The result can be accessed through the `m`-variable.
        m.forEach((match, groupIndex) => {
            console.log(`Found match, group ${groupIndex}: ${match}`);
        });
    }

    RegEx Circuit

    jex.im visualizes regular expressions:

    0 讨论(0)
  • 2020-11-22 03:09

    This is a solution

    var s = '[description:"aoeu" uuid:"123sth"]';
    
    var re = /\s*([^[:]+):\"([^"]+)"/g;
    var m;
    while (m = re.exec(s)) {
      console.log(m[1], m[2]);
    }
    

    This is based on lawnsea's answer, but shorter.

    Notice that the `g' flag must be set to move the internal pointer forward across invocations.

    0 讨论(0)
提交回复
热议问题