是否有一种方法来检索(开始)字符的位置在一个正则匹配()在Javascript的结果字符串?
当前回答
在现代浏览器中,您可以使用string.matchAll()来实现这一点。
与RegExp.exec()相比,这种方法的优点是它不依赖于正则表达式是有状态的,就像@Gumbo的答案中那样。
让regexp = /bar/g; 让STR = 'foobarfoobar'; let matches =[…str.matchAll(regexp)]; matches.forEach((match) => { Console.log ("match found at " + match.index); });
其他回答
var str = "The rain in SPAIN stays mainly in the plain";
function searchIndex(str, searchValue, isCaseSensitive) {
var modifiers = isCaseSensitive ? 'gi' : 'g';
var regExpValue = new RegExp(searchValue, modifiers);
var matches = [];
var startIndex = 0;
var arr = str.match(regExpValue);
[].forEach.call(arr, function(element) {
startIndex = str.indexOf(element, startIndex);
matches.push(startIndex++);
});
return matches;
}
console.log(searchIndex(str, 'ain', true));
来自developer.mozilla.org文档的String .match()方法:
返回的数组有一个额外的输入属性,该属性包含 被解析的原始字符串。此外,它还有一个索引 属性中匹配的从零开始的索引 字符串。
当处理一个非全局的正则表达式(即,在你的正则表达式上没有g标志)时,.match()返回的值有一个index属性…你要做的就是进入它。
var index = str.match(/regex/).index;
下面是一个例子,展示了它的工作原理:
Var STR = '我的字符串这里'; Var index = str.match(/here/).index; console.log(指数);// <- 10
我已经成功地测试了IE5。
我恐怕之前的答案(基于exec)似乎不工作的情况下,你的正则表达式匹配宽度0。例如(注意:/\b/g是应该找到所有单词边界的正则表达式):
Var re = /\b/g, STR = "hello world"; Var guard = 10; While ((match = re.exec(str)) != null) { Console.log ("match found at " + match.index); If (guard—< 0){ 控制台。错误(“检测到无限循环”) 打破; } }
可以尝试通过让正则表达式匹配至少1个字符来修复这个问题,但这远远不够理想(并且意味着您必须手动在字符串末尾添加索引)。
Var re = /\b /g, STR = "hello world"; Var guard = 10; While ((match = re.exec(str)) != null) { Console.log ("match found at " + match.index); If (guard—< 0){ 控制台。错误(“检测到无限循环”) 打破; } }
一个更好的解决方案(它只适用于较新的浏览器/需要在较旧的/IE版本上进行填充)是使用String.prototype.matchAll()
Var re = /\b/g, STR = "hello world"; console.log(Array.from(str.matchAll(re)).map(match => match.index))
解释:
String.prototype.matchAll()需要一个全局正则表达式(带有全局标志设置g的正则表达式)。然后返回一个迭代器。为了遍历和映射()迭代器,它必须转换为一个数组(这正是array .from()所做的)。与RegExp.prototype.exec()的结果类似,生成的元素根据规范有一个.index字段。
请参阅String.prototype.matchAll()和Array.from() MDN页面了解浏览器支持和填充选项。
编辑:深入挖掘一个所有浏览器都支持的解决方案
RegExp.prototype.exec()的问题是它更新了regex上的lastIndex指针,并且下次开始从以前找到的lastIndex开始搜索。
Var re = /l/g, STR = "hello world"; console.log (re.lastIndex) re.exec (str) console.log (re.lastIndex) re.exec (str) console.log (re.lastIndex) re.exec (str) console.log (re.lastIndex)
只要正则表达式匹配实际上有宽度,这就很有效。如果使用0 width正则表达式,这个指针不会增加,所以你得到了无限循环(注意:/(?=l)/g是l的前向——它在l之前匹配0-width字符串。所以它在第一次调用exec()时正确地去到索引2,然后保持在那里:
Var re = /(?=l)/g, STR = "hello world"; console.log (re.lastIndex) re.exec (str) console.log (re.lastIndex) re.exec (str) console.log (re.lastIndex) re.exec (str) console.log (re.lastIndex)
The solution (that is less nice than matchAll(), but should work on all browsers) therefore is to manually increase the lastIndex if the match width is 0 (which may be checked in different ways) var re = /\b/g, str = "hello world"; while ((match = re.exec(str)) != null) { console.log("match found at " + match.index); // alternative: if (match.index == re.lastIndex) { if (match[0].length == 0) { // we need to increase lastIndex -- this location was already matched, // we don't want to match it again (and get into an infinite loop) re.lastIndex++ } }
var str = '我的字符串在这里'; var index = str.match(/hre/).index; 警报(索引),<- 10
我很幸运地使用了这个基于matchAll的单行解决方案(我的用例需要一个字符串位置数组)
let regexp = /bar/g;
let str = 'foobarfoobar';
let matchIndices = Array.from(str.matchAll(regexp)).map(x => x.index);
console.log(matchIndices)
输出:[3,9]
推荐文章
- 一元加/数字(x)和parseFloat(x)之间的区别是什么?
- angularjs中的compile函数和link函数有什么区别
- 删除绑定中添加的事件监听器
- 很好的初学者教程socket.io?
- HtmlSpecialChars在JavaScript中等价于什么?
- React: 'Redirect'没有从' React -router-dom'中导出
- 如何在React中使用钩子强制组件重新渲染?
- 我如何使用Jest模拟JavaScript的“窗口”对象?
- 我如何等待一个承诺完成之前返回一个函数的变量?
- 在JavaScript中根据键值查找和删除数组中的对象
- 使嵌套JavaScript对象平放/不平放的最快方法
- 如何以及为什么'a'['toUpperCase']()在JavaScript工作?
- 有Grunt生成index.html不同的设置
- 文档之间的区别。addEventListener和window。addEventListener?
- 如何检查动态附加的事件监听器是否存在?