back to listing index

How do I retrieve all matches for a regular expression in JavaScript?

[web search]
Original source (stackoverflow.com)
Tags: regular-expressions javascript
Clipped on: 2016-05-01

I am new to regular expressions. I'm trying to parse the following kind of string:

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

where there are arbitrary key:"val" pairs inside. I want to grab the key name and the value. For those curious I'm trying to parse the database format of task warrior. Here is my test string:

[description:"aoeu" uuid:"123sth"] which is meant to highlight that anything can be in a key or value aside from space, no spaces around the colons, and values are always in double quotes. In node, this is my output:

[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 get all matches back?

asked Jun 12 '11 at 17:27
Image (Asset 2/8) alt=
gatlin
83116
   upvote
  flag
It might be that my regex is wrong and / or that I am simply using the regex facilities in JavaScript incorrectly. This seems to work: > var s = "Fifteen is 15 and eight is 8"; > var re = /\d+/g; > var m = s.match(re); m = [ '15', '8' ] – gatlin Jun 12 '11 at 18:08
   upvote
  flag
Javascript now has a .match() function: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Used like this: "some string".match(/regex/g) – Stefnotch Mar 5 at 9:37
up vote 33 down vote accepted

Continue calling re.exec(s) in a loop to obtain all the 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 it with this jsfiddle: http://jsfiddle.net/7yS2V/

answered Jun 12 '11 at 18:06
Image (Asset 3/8) alt=
lawnsea
2,9031415
1 upvote
  flag
Why not while instead of do … while? – Gumbo Jun 12 '11 at 18:14
   upvote
  flag
Thank you very much! This is very illuminating on several levels. – gatlin Jun 12 '11 at 18:19
2 upvote
  flag
Using a while loop makes it slightly awkward to initialize m. You either have to write while(m = re.exec(s)), which is an anti-pattern IMO, or you have to write m = re.exec(s); while (m) { ... m = re.exec(s); }. I prefer the do ... if ... while idiom, but other techniques would work as well. – lawnsea Jun 12 '11 at 18:21
3 upvote
  flag
doing this in chromium resulted in my tab crashing. – EdgeCaseBerg Dec 16 '14 at 18:53
4 upvote
  flag
@EdgeCaseBerg You need to have the g flag set, otherwise the internal pointer is not moved forward. Docs. – Tim Jul 25 '15 at 13:45

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.

answered Jun 5 '14 at 8:17
Image (Asset 5/8) alt=
lovasoa
944911

Based on Agus's function, but I prefer return just the match 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: [>, <]
answered Jul 21 '15 at 17:44
Image (Asset 6/8) alt=
bob
1,7401017

Here is my function to get the 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]);
});
answered May 2 '15 at 6:57
Image (Asset 7/8) alt=

To loop within a string, you can fake a replace:

var re = /\s*([^[:]+):\"([^"]+)"/g;
var s = '[description:"aoeu" uuid:"123sth"]';
s.replace(re,function($0,$1,$2){console.log($1+","+$2+"<br/>");});
answered Jul 12 '12 at 1:35
Image (Asset 8/8) alt=
Christophe
10.9k85095

Your Answer

asked

4 years ago

viewed

15158 times

active

9 months ago

Hot Network Questions

Technology Life / Arts Culture / Recreation Science Other
  1. Stack Overflow
  2. Server Fault
  3. Super User
  4. Web Applications
  5. Ask Ubuntu
  6. Webmasters
  7. Game Development
  8. TeX - LaTeX
  1. Programmers
  2. Unix & Linux
  3. Ask Different (Apple)
  4. WordPress Development
  5. Geographic Information Systems
  6. Electrical Engineering
  7. Android Enthusiasts
  8. Information Security
  1. Database Administrators
  2. Drupal Answers
  3. SharePoint
  4. User Experience
  5. Mathematica
  6. Salesforce
  7. ExpressionEngine® Answers
  8. more (13)
  1. Photography
  2. Science Fiction & Fantasy
  3. Graphic Design
  4. Movies & TV
  5. Seasoned Advice (cooking)
  6. Home Improvement
  7. Personal Finance & Money
  8. Academia
  9. more (9)
  1. English Language & Usage
  2. Skeptics
  3. Mi Yodeya (Judaism)
  4. Travel
  5. Christianity
  6. Arqade (gaming)
  7. Bicycles
  8. Role-playing Games
  9. more (21)
  1. Mathematics
  2. Cross Validated (stats)
  3. Theoretical Computer Science
  4. Physics
  5. MathOverflow
  6. Chemistry
  7. Biology
  8. more (5)
  1. Stack Apps
  2. Meta Stack Exchange
  3. Area 51
  4. Stack Overflow Careers
site design / logo © 2016 Stack Exchange Inc; user contributions licensed under cc by-sa 3.0 with attribution required
rev 2016.4.29.3525