在javascript中,是否有一个string . indexof()的等效,为第一个参数接受正则表达式而不是字符串,同时仍然允许第二个参数?

我需要做点什么

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

and

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

虽然String.search()接受regexp作为参数,但它不允许我指定第二个参数!

编辑: 这比我最初想象的要难,所以我写了一个小测试函数来测试所有提供的解决方案……它假设regexIndexOf和regexLastIndexOf已经添加到String对象中。

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)]) ;
    }
}

我正在进行如下测试,以确保至少对于一个字符regexp,如果我们使用indexOf,结果是相同的

在 xes 中寻找 a 测试(“xxx”); 测试('axx'); 测试(“xax”); 测试(“XXA”); 测试(“AXA”); 测试(“xaa”); 测试(“AAX”); 测试(“AAA”);


当前回答

在某些简单的情况下,您可以通过使用split简化向后搜索。

function regexlast(string,re){
  var tokens=string.split(re);
  return (tokens.length>1)?(string.length-tokens[tokens.length-1].length):null;
}

这有一些严重的问题:

重叠的匹配不会显示出来 返回的索引是匹配的结束,而不是开始(如果你的regex是一个常量,没问题)

但从好的方面来看,它的代码更少。对于一个不能重叠的定长正则表达式(比如/\s\w/用于查找单词边界),这已经足够好了。

其他回答

杰森·邦廷的最后一个指数不成立。我的方法不是最优的,但有效。

//Jason Bunting's
String.prototype.regexIndexOf = function(regex, startpos) {
var indexOf = this.substring(startpos || 0).search(regex);
return (indexOf >= 0) ? (indexOf + (startpos || 0)) : indexOf;
}

String.prototype.regexLastIndexOf = function(regex, startpos) {
var lastIndex = -1;
var index = this.regexIndexOf( regex );
startpos = startpos === undefined ? this.length : startpos;

while ( index >= 0 && index < startpos )
{
    lastIndex = index;
    index = this.regexIndexOf( regex, index + 1 );
}
return lastIndex;
}

根据BaileyP的回答。主要的区别是,如果模式不能匹配,这些方法将返回-1。

编辑:感谢Jason Bunting的回答,我有了一个想法。为什么不修改正则表达式的.lastIndex属性?尽管这只适用于带有全局标志(/g)的模式。

编辑:更新以通过测试用例。

String.prototype.regexIndexOf = function(re, startPos) {
    startPos = startPos || 0;

    if (!re.global) {
        var flags = "g" + (re.multiline?"m":"") + (re.ignoreCase?"i":"");
        re = new RegExp(re.source, flags);
    }

    re.lastIndex = startPos;
    var match = re.exec(this);

    if (match) return match.index;
    else return -1;
}

String.prototype.regexLastIndexOf = function(re, startPos) {
    startPos = startPos === undefined ? this.length : startPos;

    if (!re.global) {
        var flags = "g" + (re.multiline?"m":"") + (re.ignoreCase?"i":"");
        re = new RegExp(re.source, flags);
    }

    var lastSuccess = -1;
    for (var pos = 0; pos <= startPos; pos++) {
        re.lastIndex = pos;

        var match = re.exec(this);
        if (!match) break;

        pos = match.index;
        if (pos <= startPos) lastSuccess = pos;
    }

    return lastSuccess;
}

我有一个简短的版本给你。这对我来说很有效!

var match      = str.match(/[abc]/gi);
var firstIndex = str.indexOf(match[0]);
var lastIndex  = str.lastIndexOf(match[match.length-1]);

如果你想要一个原型版本:

String.prototype.indexOfRegex = function(regex){
  var match = this.match(regex);
  return match ? this.indexOf(match[0]) : -1;
}

String.prototype.lastIndexOfRegex = function(regex){
  var match = this.match(regex);
  return match ? this.lastIndexOf(match[match.length-1]) : -1;
}

编辑:如果你想添加对fromIndex的支持

String.prototype.indexOfRegex = function(regex, fromIndex){
  var str = fromIndex ? this.substring(fromIndex) : this;
  var match = str.match(regex);
  return match ? str.indexOf(match[0]) + fromIndex : -1;
}

String.prototype.lastIndexOfRegex = function(regex, fromIndex){
  var str = fromIndex ? this.substring(0, fromIndex) : this;
  var match = str.match(regex);
  return match ? str.lastIndexOf(match[match.length-1]) : -1;
}

要使用它,就像这样简单:

var firstIndex = str.indexOfRegex(/[abc]/gi);
var lastIndex  = str.lastIndexOfRegex(/[abc]/gi);

你可以使用substr。

str.substr(i).match(/[abc]/);

String构造函数的实例有一个.search()方法,该方法接受RegExp并返回第一个匹配项的索引。

要从特定位置开始搜索(伪造.indexOf()的第二个参数),可以切掉前i个字符:

str.slice(i).search(/re/)

但这将获得较短字符串的索引(在第一部分被切掉之后),因此如果返回的索引不是-1,则需要将切掉的部分(i)的长度添加到返回的索引中。这将给你原始字符串的索引:

function regexIndexOf(text, re, i) {
    var indexInSuffix = text.slice(i).search(re);
    return indexInSuffix < 0 ? indexInSuffix : indexInSuffix + i;
}