是否有一种方法来检索(开始)字符的位置在一个正则匹配()在Javascript的结果字符串?
当前回答
我恐怕之前的答案(基于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++ } }
其他回答
Exec返回一个带有index属性的对象:
Var match = /bar/.exec("foobar"); If (match) { Console.log ("match found at " + match.index); }
对于多个匹配:
Var re = /bar/g, STR = "foobarfoobar"; While ((match = re.exec(str)) != null) { Console.log ("match found at " + match.index); }
我很幸运地使用了这个基于matchAll的单行解决方案(我的用例需要一个字符串位置数组)
let regexp = /bar/g;
let str = 'foobarfoobar';
let matchIndices = Array.from(str.matchAll(regexp)).map(x => x.index);
console.log(matchIndices)
输出:[3,9]
在现代浏览器中,您可以使用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); });
我恐怕之前的答案(基于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 text = "border-bottom-left-radius";
var newText = text.replace(/-/g,function(match, index){
return " " + index + " ";
});
返回:"border 6 bottom 13 left 18 radius"
看来这就是你要找的东西。
推荐文章
- 一元加/数字(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?
- 如何检查动态附加的事件监听器是否存在?