javascriptregexindexof

JavaScript: String.indexOf(...) allowing regular-expressions?


In javascript, is there an equivalent of String.indexOf(...) that takes a regular expression instead of a string for the first parameter, while still allowing a second parameter ?

I need to do something like

str.indexOf(/[abc]/ , i);

and

str.lastIndexOf(/[abc]/ , i);

While String.search() takes a regexp as a parameter it does not allow me to specify a second argument!

Edit:
This turned out to be harder than I originally thought so I wrote a small test function to test all the provided solutions... it assumes regexIndexOf and regexLastIndexOf have been added to the String object.

function test (str) {
    var i = str.length +2;
    while (i--) {
        if (str.indexOf('a',i) != str.regexIndexOf(/a/,i)) 
            alert (['failed regexIndexOf ' , str,i , str.indexOf('a',i) , str.regexIndexOf(/a/,i)]) ;
        if (str.lastIndexOf('a',i) != str.regexLastIndexOf(/a/,i) ) 
            alert (['failed regexLastIndexOf ' , str,i,str.lastIndexOf('a',i) , str.regexLastIndexOf(/a/,i)]) ;
    }
}

and I am testing as follow to make sure that at least for one character regexp, the result is the same as if we used indexOf

//Look for the a among the xes
test('xxx');
test('axx');
test('xax');
test('xxa');
test('axa');
test('xaa');
test('aax');
test('aaa');


Solution

  • Combining a few of the approaches already mentioned (the indexOf is obviously rather simple), I think these are the functions that will do the trick:

    function regexIndexOf(string, regex, startpos) {
        var indexOf = string.substring(startpos || 0).search(regex);
        return (indexOf >= 0) ? (indexOf + (startpos || 0)) : indexOf;
    }
    
    function regexLastIndexOf(string, regex, startpos) {
        regex = (regex.global) ? regex : new RegExp(regex.source, "g" + (regex.ignoreCase ? "i" : "") + (regex.multiLine ? "m" : ""));
        if(typeof (startpos) == "undefined") {
            startpos = string.length;
        } else if(startpos < 0) {
            startpos = 0;
        }
        var stringToWorkWith = string.substring(0, startpos + 1);
        var lastIndexOf = -1;
        var nextStop = 0;
        var result;
        while((result = regex.exec(stringToWorkWith)) != null) {
            lastIndexOf = result.index;
            regex.lastIndex = ++nextStop;
        }
        return lastIndexOf;
    }
    

    UPDATE: Edited regexLastIndexOf() so that is seems to mimic lastIndexOf() now. Please let me know if it still fails and under what circumstances.


    UPDATE: Passes all tests found on in comments on this page, and my own. Of course, that doesn't mean it's bulletproof. Any feedback appreciated.