yotamoo
yotamoo

Reputation: 5452

Find all matching regex patterns and index of the match in the string

I want to find /AA/ pattern in AA-AA-AA subject string. I need to get the matching string and the position (index) of the match.

I have looked at RegExp.prototype.exec(). It only returns the first match:

/AA/g.exec('AA-AA-AA')

Upvotes: 8

Views: 13506

Answers (4)

Scott Wager
Scott Wager

Reputation: 868

An alternative to bobince's answer is to use the 'lastIndex' property of the regex to get the end index of each match

var match, indexes= [];
while (match = r.exec(value)) {
    indexes.push([match.index, r.lastIndex]);
}

Upvotes: 0

Gajus
Gajus

Reputation: 73788

Be careful when using RegExp.prototype.exec() function to match a string. The constructed regex object is stateful, i.e. every time you call .exec() it affects the lastIndex property of the regex instance. Therefore, you should always reset the lastIndex property before using an instance of regex object.

let re,
    findAAs;

re = /AA/;

findAAs = (input) => {
    let match;

    // `re` is cached instance of regex object.
    // Reset `re.lastIndex` every time before using it.

    re.lastIndex = 0;

    while ((match = re.exec(input)) !== null) {
        match.index; // Match index.
        match[0]; // Matching string.
    }
};

A tempting alternative is to construct the regex object on every execution. Depending on how resource intensive your task is, this is an option too.

let findAAs;

findAAs = (input) => {
    let match,
        re;

    re = /AA/;

    while ((match = re.exec(input)) !== null) {
        match.index; // Match index.
        match[0]; // Matching string.
    }
};

A pragmatic alternative to using .exec() is String.prototype.replace().

let findAAs,
    re;

re = /AA/;

findAAs = (input) => {
    let match,
        re;

    input.replace(re, (match, index) => {
        match; // Matching string.
        index; // Match index.

        return '';
    });
};

The downside of this approach is that it constructs a copy of the subject string.

Whether you should use it or not, depends on how resource intensive your task is. Personally, I like to avoid while blocks in my code and therefore prefer the .replace() approach.

Upvotes: 3

mplungjan
mplungjan

Reputation: 177691

http://jsfiddle.net/mplungjan/MNXvQ/

I think this is easier to grasp

var str = "AAbAAcAAd"
var re = /(AA)/gi;
var t="",cnt=0;
while ((result=re.exec(str))!=null) {
    document.write((cnt++)+":"+result[1]+"<br />")        
}

re.lastIndex contains the positions each time

Upvotes: 0

bobince
bobince

Reputation: 536349

exec() only returns a single match. To get all matches with a g​lobal regexp, you have to call it repeatedly, eg.:

var match, indexes= [];
while (match= r.exec(value))
    indexes.push([match.index, match.index+match[0].length]);

Upvotes: 19

Related Questions