当前位置:  开发笔记 > 编程语言 > 正文

是否有允许正则表达式的JavaScript的String.indexOf()版本?

如何解决《是否有允许正则表达式的JavaScript的String.indexOf()版本?》经验,为你挑选了7个好方法。

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

我需要做点什么

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

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
test('xxx')中查找a ;
试验( 'AXX');
试验( 'XAX');
试验( 'XXA');
试验( 'AXA');
试验( '的Xaa');
试验( 'AAX');
试验( 'AAA');



1> Glenn..:

所述的实例String构造有一个.search()方法,它接受一个正则表达式并返回第一匹配的索引.

要从特定位置开始搜索(伪造第二个参数.indexOf()),您可以slice关闭第一个i字符:

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

但是这将得到较短的字符串中的索引(在第一部分被切掉之后),所以你想要将截断的part(i)的长度添加到返回的索引(如果不是)-1.这将为您提供原始字符串中的索引:

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


str.substr(ⅰ).search(/重新/)
很好的解决方案,但输出有点不同.indexOf将从头开始返回一个数字(无论偏移量如何),而这将从偏移量返回位置.所以,对于奇偶校验,你会想要更像这样的东西:`function regexIndexOf(text,offset){var initial = text.substr(offset).search(/ re /); if(initial> = 0){initial + = offset; } return initial; }`

2> Jason Buntin..:

结合已经提到的一些方法(indexOf显然相当简单),我认为这些功能可以解决这个问题:

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

显然,修改内置String对象会为大多数人发送红色标记,但这可能是一次没有那么大的交易; 只是意识到这一点.


更新:编辑regexLastIndexOf(),这似乎lastIndexOf()现在模仿.如果仍然失败并在什么情况下,请告诉我.


更新:通过本页评论中找到的所有测试,以及我自己的测试.当然,这并不意味着它是防弹的.任何反馈意见.


我认为使用`regex.lastIndex = result.index + 1;`代替`regex.lastIndex = ++ nextStop;`更有效率.它会更快地进入下一场比赛而不会失去任何结果.

3> pmrotule..:

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

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



4> rmg.n3t..:

使用:

str.search(regex)

请参阅此处的文档.


@OZZIE:不,不是真的.它基本上是[格伦的回答](/sf/ask/17360801/)(约150支票),除了**没有任何解释**,**不支持**起始位置除了`0`,并被发布了......**七年**之后.

5> Markus Jarde..:

根据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;
}



6> Andru Luvisi..:

你可以使用substr.

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



7> Prestaul..:

RexExp实例已经具有lastIndex属性(如果它们是全局的),所以我正在做的是复制正则表达式,对其进行略微修改以满足我们的目的,将exec其放在字符串上并查看lastIndex。这将不可避免地比在字符串上循环快。(您有足够的示例说明如何将其放入字符串原型,对吗?)

function reIndexOf(reIn, str, startIndex) {
    var re = new RegExp(reIn.source, 'g' + (reIn.ignoreCase ? 'i' : '') + (reIn.multiLine ? 'm' : ''));
    re.lastIndex = startIndex || 0;
    var res = re.exec(str);
    if(!res) return -1;
    return re.lastIndex - res[0].length;
};

function reLastIndexOf(reIn, str, startIndex) {
    var src = /\$$/.test(reIn.source) && !/\\\$$/.test(reIn.source) ? reIn.source : reIn.source + '(?![\\S\\s]*' + reIn.source + ')';
    var re = new RegExp(src, 'g' + (reIn.ignoreCase ? 'i' : '') + (reIn.multiLine ? 'm' : ''));
    re.lastIndex = startIndex || 0;
    var res = re.exec(str);
    if(!res) return -1;
    return re.lastIndex - res[0].length;
};

reIndexOf(/[abc]/, "tommy can eat");  // Returns 6
reIndexOf(/[abc]/, "tommy can eat", 8);  // Returns 11
reLastIndexOf(/[abc]/, "tommy can eat"); // Returns 11

您也可以将函数原型制作到RegExp对象上:

RegExp.prototype.indexOf = function(str, startIndex) {
    var re = new RegExp(this.source, 'g' + (this.ignoreCase ? 'i' : '') + (this.multiLine ? 'm' : ''));
    re.lastIndex = startIndex || 0;
    var res = re.exec(str);
    if(!res) return -1;
    return re.lastIndex - res[0].length;
};

RegExp.prototype.lastIndexOf = function(str, startIndex) {
    var src = /\$$/.test(this.source) && !/\\\$$/.test(this.source) ? this.source : this.source + '(?![\\S\\s]*' + this.source + ')';
    var re = new RegExp(src, 'g' + (this.ignoreCase ? 'i' : '') + (this.multiLine ? 'm' : ''));
    re.lastIndex = startIndex || 0;
    var res = re.exec(str);
    if(!res) return -1;
    return re.lastIndex - res[0].length;
};


/[abc]/.indexOf("tommy can eat");  // Returns 6
/[abc]/.indexOf("tommy can eat", 8);  // Returns 11
/[abc]/.lastIndexOf("tommy can eat"); // Returns 11

关于如何修改的快速说明RegExp:因为indexOf我只需要确保设置了全局标志即可。对于lastIndexOf,我正在使用否定的超前查找来查找最后一次出现,除非RegExp该字符串已在字符串末尾匹配。

推荐阅读
mylvfamily
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有