6

If I run this:

'121'.match(/[0-9]{2}/gi)

I get back an array with a single result:

['12']

How can I get it to return all results, even if they overlap? I want the result to be this:

['12', '21']

EDIT: Or a better example would be:

'1234567'.match(...);

should give me an array with

[12, 23, 34, 45, 56, 67]

Nick
  • 5,228
  • 9
  • 40
  • 69
  • 1
    I'm trying to get both '12' and '21' out of that string -- instead I just get '12' because the regex engine stops after it finds a match. – Nick Nov 23 '11 at 00:43

5 Answers5

8

This works with most pcre engines.
Capture 2, consume 1.

/(?=(\d\d))\d/g

var pat = /(?=(\d\d))\d/g;
var results = [];
var match;

while ((match = pat.exec('1234567')) != null) {
  results.push(match[1]);
}

console.log(results);

Output: 12,23,34,45,56,67

mplungjan
  • 169,008
  • 28
  • 173
  • 236
3

this just won't work in the way you want.

when you specify pattern [0-9]{2}, match() looks up first occurrence of two digit number, then continues search from that place on. as string length is 3, obviously it won't find another match.

you should use different algorithm for finding all two digit numbers. I would suggest using combination of your first match and do one more with following regex

/[0-9]([0-9]{2})/ and combine sets of both first and second run.

jancha
  • 4,916
  • 1
  • 24
  • 39
3

You can do it like this:

var str = '121';
var results = [];
var re = /[0-9]{2}/gi, matches;
while (matches = re.exec(str)) {
    results.push(matches[0]);
    re.lastIndex -= (matches[0].length - 1);  // one past where it matched before
}
// results is an array of matches here

It takes multiple calls to .exec() and then you have to manipulate the .lastIndex value so it will start where you want it to look again.

You can see it work here: http://jsfiddle.net/jfriend00/XsNe5/.

You can read about how calling .exec() multiple times works here: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/RegExp/exec.

function elem(id) {
    return document.getElementById(id);
}

function test() {
  var str = elem("data").value;
  var results = [];
  var re = /[0-9]{2}/gi,
    matches;
  while (matches = re.exec(str)) {
    results.push(matches[0]);
    re.lastIndex -= (matches[0].length - 1);
  }
  elem("result").innerHTML = results.join("<br>");
}

elem("go").onclick = test;
<input id="data" type="text" value="1234567890"><br>
<button id="go">Test</button>
<div id="result"></div>
jfriend00
  • 683,504
  • 96
  • 985
  • 979
1

It's not very concise, but this:

var matches = [];
'1234567'.replace
(
  /(?=[0-9]{2})/gi,
  function(s,pos,str)
  {
    matches.push(str.substr(pos, 2));
  }
);

will set matches to ['12','23','34','45','56','67']. It works by using a lookahead assertion to find matches without actually swallowing them. (The replace doesn't actually replace anything in this case; it's just a convenient way to apply a closure to all instances of a regex-match in a given string.)

ruakh
  • 175,680
  • 26
  • 273
  • 307
1

Here is another example using lookaheads

var str = "12345",
    regexp = /\d(?=(\d))/g,
    results = [],
    m = null;

while(m = regexp.exec(str)) results.push(m.join(''));

alert(results) // 12,23,34,45

Same idea as ruakh, but a slightly different approach.

J. Holmes
  • 18,466
  • 5
  • 47
  • 52