How to get all matches for regular expression in JavaScript?

I am new to regular expressions. I am trying to parse the following string type:

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

where there is an arbitrary key: pairs "val" inside. I want to get the name and value of the key. For the curious, I am trying to parse the format of the warrior database of a task. Here is my test line:

[description:"aoeu" uuid:"123sth"] , which is intended to emphasize that something can be in the key or value aside from space, without spaces around the colons, and the values ​​are always enclosed in double quotes. In node, this is my conclusion:

 [deuteronomy][gatlin][~]$ node > var re = /^\[(?:(.+?):"(.+?)"\s*)+\]$/g > re.exec('[description:"aoeu" uuid:"123sth"]'); [ '[description:"aoeu" uuid:"123sth"]', 'uuid', '123sth', index: 0, input: '[description:"aoeu" uuid:"123sth"]' ] 

But description:"aoeu" also matches this pattern. How can I return all matches?

+151
javascript regex regex-group taskwarrior
Jun 12 '11 at 17:27
source share
17 answers

Continue to call re.exec(s) in a loop to get all matches:

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

Try this with this JSFiddle: https://jsfiddle.net/7yS2V/

+203
Jun 12 '11 at 18:06
source share

str.match(pattern) , if pattern has the global flag g , will return all matches as an array.

For example:

 const str = 'All of us except @Emran, @Raju and @Noman was there'; console.log( str.match(/@\w*/g) ); // Will log ["@Emran", "@Raju", "@Noman"] 
+96
Apr 25 '17 at 22:35
source share

To iterate over all matches, you can use the replace function:

 var re = /\s*([^[:]+):\"([^"]+)"/g; var s = '[description:"aoeu" uuid:"123sth"]'; s.replace(re, function(match, g1, g2) { console.log(g1, g2); }); 
+84
Jul 12 2018-12-12T00:
source share

This decision

 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.

Note that the `g 'flag must be set to move the internal pointer forward on calls.

+54
Jun 05 '14 at 8:17
source share
 str.match(/regex/g) 

returns all matches as an array.

If for some mysterious reason you need additional information that comes with exec as an alternative to the previous answers, you can do this with a recursive function instead of a loop like this (which also looks cooler).

 function findMatches(regex, str, matches = []) { const res = regex.exec(str) res && matches.push(res) && findMatches(regex, str, matches) return matches } // Usage const matches = findMatches(/regex/g, str) 

as mentioned in the comments earlier, it is important to have g at the end of the regex definition to move the pointer forward with each execution.

+15
Nov 21 '18 at 23:44
source share

Based on an Agus function, but I prefer to return only matching values:

 var bob = "> bob <"; function matchAll(str, regex) { var res = []; var m; if (regex.global) { while (m = regex.exec(str)) { res.push(m[1]); } } else { if (m = regex.exec(str)) { res.push(m[1]); } } return res; } var Amatch = matchAll(bob, /(&.*?;)/g); console.log(Amatch); // yeilds: [>, <] 
+9
Jul 21 '15 at 17:44
source share

Iterations are better:

 const matches = (text, pattern) => ({ [Symbol.iterator]: function * () { const clone = new RegExp(pattern.source, pattern.flags); let match = null; do { match = clone.exec(text); if (match) { yield match; } } while (match); } }); 

Use in a loop:

 for (const match of matches('abcdefabcdef', /ab/g)) { console.log(match); } 

Or if you want an array:

 [ ...matches('abcdefabcdef', /ab/g) ] 
+7
May 22 '18 at
source share

Finally, we begin to see the built-in matchAll function, see the description and compatibility table here . It appears that as of April 2019, Chrome and Firefox are supported, but not IE, Edge, Opera, or Node.js. It seems like it was compiled in December 2018, so give it some time to cover all browsers, but I believe that it will be there.

The built-in matchAll function matchAll good because it returns an iteration . He also returns capture groups for every match! So you can do things like

 // get the letters before and after "o" let matches = "stackoverflow".matchAll(/(\w)o(\w)/g); for (match of matches) { console.log("letter before:" + match[1]); console.log("letter after:" + match[2]); } arrayOfAllMatches = [...matches]; // you can also turn the iterable into an array 

It also seems that each match object uses the same format as match() . Thus, each object is an array of matching and capture groups, as well as three additional properties index , input and groups . So it looks like this:

 [<match>, <group1>, <group2>, ..., index: <match offset>, input: <original string>, groups: <named capture groups>] 

For more information on matchAll there is also a Google Developers page . Polyphiles / gaskets are also available.

+6
Apr 08 '19 at 12:09 on
source share

Here is my function for getting matches:

 function getAllMatches(regex, text) { if (regex.constructor !== RegExp) { throw new Error('not RegExp'); } var res = []; var match = null; if (regex.global) { while (match = regex.exec(text)) { res.push(match); } } else { if (match = regex.exec(text)) { res.push(match); } } return res; } var regex = /abc|def|ghi/g; var res = getAllMatches(regex, 'abcdefghi'); res.forEach(function (item) { console.log(item[0]); }); 
+4
May 02 '15 at 6:57
source share

If your system (Chrome / Node.js / Firefox) supports ES9, use the new .matchAll() . If you have an old system, there is a function for easy copying and pasting.

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

usage example:

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

outputs:

 [ [ 'blah', index: 0 ], [ 'blah', index: 6 ] ] 
+3
Jan 21 '18 at 8:50
source share

Starting with ES9, there is now an easier and better way to get all matches along with information about capture groups and their indices:

 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 chop rice", groups: not defined]

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

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

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

+1
May 09 '19 at 7:05
source share

Use this ...

 var all_matches = your_string.match(re); console.log(all_matches) 

It will return an array of all matches ... It will work just fine ... But remember that it will not account for groups ... It will simply return full matches ...

0
Mar 11 '18 at 11:05
source share

I would definitely recommend using the String.match () function and creating an appropriate RegEx for it. My example is a list of strings, which is often needed when scanning user input for keywords and phrases.

  // 1) Define keywords var keywords = ['apple', 'orange', 'banana']; // 2) Create regex, pass "i" for case-insensitive and "g" for global search regex = new RegExp("(" + keywords.join('|') + ")", "ig"); => /(apple|orange|banana)/gi // 3) Match it against any string to get all matches "Test string for ORANGE or apples were mentioned".match(regex); => ["ORANGE", "apple"] 

Hope this helps!

0
Jun 06 '18 at 22:13
source share

In fact, this will not help solve your more complex problem, but I will report it anyway, because it is a simple solution for people who do not perform a global search like you.

I have simplified the regular expression in the answer so that it is more understandable (this is not a solution to your specific problem).

 var re = /^(.+?):"(.+)"$/ var regExResult = re.exec('description:"aoeu"'); var purifiedResult = purify_regex(regExResult); // We only want the group matches in the array function purify_regex(reResult){ // Removes the Regex specific values and clones the array to prevent mutation let purifiedArray = [...reResult]; // Removes the full match value at position 0 purifiedArray.shift(); // Returns a pure array without mutating the original regex result return purifiedArray; } // purifiedResult= ["description", "aoeu"] 

It looks more verbose than because of the comments, here is how it looks without comments

 var re = /^(.+?):"(.+)"$/ var regExResult = re.exec('description:"aoeu"'); var purifiedResult = purify_regex(regExResult); function purify_regex(reResult){ let purifiedArray = [...reResult]; purifiedArray.shift(); return purifiedArray; } 

Note that any groups that do not match will be listed in the array as undefined values.

This solution uses the ES6 distribution operator to clear an array of specific regex values. You will need to run your code through Babel if you want IE11 support.

0
Jul 10 '18 at 12:06
source share

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

The order is stored in the resulting list.

Potential disadvantages

  1. He clones a regular expression for each match.
  2. The result is in a different form than the expected solutions. You will need to process them again.
 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
May 23 '19 at 2:07
source share

I used the class from the Mozilla documentation :

 class MyRegExp extends RegExp { [Symbol.matchAll](str) { let result = RegExp.prototype[Symbol.matchAll].call(this, str); if (!result) { return null; } return Array.from(result); } } let re = new MyRegExp('-[0-9]+', 'g'); console.log('2016-01-02|2019-03-07'.matchAll(re)); // expected output: Array [Array ["-01"], Array ["-02"], Array ["-03"], Array ["-07"]] 
0
Jul 18 '19 at 9:59
source share

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(',')); 
-5
Jul 03 '17 at 6:24
source share



All Articles