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

IT技术 javascript regex indexof
2021-01-27 08:30:08

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

我需要做类似的事情

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

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

虽然 String.search() 将正则表达式作为参数,但它不允许我指定第二个参数!

编辑:
结果证明这比我原先想象的要难,所以我写了一个小测试函数来测试所有提供的解决方案......它假设 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)]) ;
    }
}

我正在测试如下以确保至少对于一个字符正则表达式,结果与我们使用 indexOf 相同

//在xes中寻找a
test('xxx');
测试('axx');
测试('xax');
测试('xxa');
测试('axa');
测试('xaa');
测试('aax');
测试('aaa');

6个回答

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

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

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

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

function regexIndexOf(text, re, i) {
    var indexInSuffix = text.slice(i).search(re);
    return indexInSuffix < 0 ? indexInSuffix : indexInSuffix + i;
}
str.substr(i).search(/re/)
2021-03-27 08:30:08
如果 i 未定义(它是可选的),则此代码将不起作用。因此,输入检查更简单的版本: regexIndexOf(text, re, i) { let idx = (i && i > 0) ? text.substr(i).search(re) : text.search(re); 返回 idx < 0 ?idx : idx + (i?i:0); }
2021-04-02 08:30:08
很好的解决方案,但是输出有点不同。indexOf 将从头开始返回一个数字(无论偏移量如何),而这将返回偏移量的位置。所以,为了平价,你会想要更像这样的东西:function regexIndexOf(text, offset) { var initial = text.substr(offset).search(/re/); if(initial >= 0) { initial += offset; } return initial; }
2021-04-08 08:30:08
来自问题:虽然 String.search() 将正则表达式作为参数,但它不允许我指定第二个参数!
2021-04-12 08:30:08

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

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;
    while((result = regex.exec(stringToWorkWith)) != null) {
        lastIndexOf = result.index;
        regex.lastIndex = ++nextStop;
    }
    return lastIndexOf;
}

更新:已编辑regexLastIndexOf(),现在似乎在模仿lastIndexOf()请让我知道它是否仍然失败以及在什么情况下。


更新:通过本页评论中发现的所有测试,以及我自己的测试。当然,这并不意味着它是防弹的。任何反馈表示赞赏。

对不起,不是一个巨大的正则表达式人 - 你能给我一个会让我失败的例子吗?我很高兴能够学到更多,但你的回答对我这样无知的人没有帮助。:)
2021-03-13 08:30:08
regexLastIndexOf将只返回最后一个非重叠匹配项的索引
2021-03-30 08:30:08
Jason 我刚刚添加了一些功能来测试这个问题。这是失败(在其他测试中)以下 'axx'.lastIndexOf('a',2) != 'axx'.regexLastIndexOf(/a/,2)
2021-04-02 08:30:08
我认为使用regex.lastIndex = result.index + 1;而不是regex.lastIndex = ++nextStop;. 它将以更快的速度进入下一场比赛,希望不会失去任何结果。
2021-04-02 08:30:08
如果您更喜欢从 npm 中提取它,这两个 util 函数现在在 NPM 上为:npmjs.com/package/index-of-regex
2021-04-04 08:30:08

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

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);
lastIndexOfRegex还应该将 的值加回到fromIndex结果中。
2021-03-13 08:30:08
绝妙的把戏。为了处理 CoralK 指出的情况,您可以将indexOfRegex的 return 语句替换为: if(match){let list=this.split(regex);match.pop();list.pop();return match.join('').length+list.join('').length+(fromIndex||0);}else return -1;
2021-03-14 08:30:08
这实际上是一个很好的技巧。如果扩大它也采取了将是巨大的startIndex参数,像往常一样indeoxOflastIndexOf做。
2021-03-16 08:30:08
您的算法将在以下情况下崩溃:"aRomeo Romeo".indexOfRegex(new RegExp("\\bromeo", 'gi'));结果将是 1,而应该是 7,因为 indexOf 将查找第一次出现的“romeo”,无论它是否位于单词的开头。
2021-03-16 08:30:08
@RobertKoritnik - 我编辑了我的答案以支持startIndex(或fromIndex)。希望能帮助到你!
2021-03-21 08:30:08

利用:

str.search(regex)

请参阅此处的文档

@OZZIE:不,不是真的。这基本上是Glenn 的回答(大约有 150 票),除了它没有任何解释,不支持除 之外的起始位置0,并且在7 年发布
2021-03-22 08:30:08

你可以使用 substr。

str.substr(i).match(/[abc]/);
您能否编辑您的答案以提供有效的演示代码?
2021-03-19 08:30:08
那不是问题。如果您真的很担心,请改用 String.substring() - 您只需要以不同的方式进行数学计算即可。此外,JavaScript 不应该 100% 受制于它的母语言。
2021-03-21 08:30:08
这不是一个问题——如果你让你的代码针对一个没有实现 substr 的实现运行,因为他们想要遵守 ECMAScript 标准,你就会遇到问题。当然,用 substring 替换它并不难,但是意识到这一点很好。
2021-03-23 08:30:08
当您遇到问题时,您有一个非常非常简单的解决方案。我认为这些评论是明智的,但否决票是迂腐的。
2021-04-05 08:30:08
来自 O'Reilly 出版的著名 JavaScript 书籍:“substr 尚未被 ECMAScript 标准化,因此已被弃用。” 但我喜欢你所得到的背后的基本思想。
2021-04-10 08:30:08