如何在JavaScript regexp中获取子模式的索引?
我用JavaScript编写了一个正则表达式,用于在字符串中搜索如何在JavaScript regexp中获取子模式的索引?,javascript,regex,Javascript,Regex,我用JavaScript编写了一个正则表达式,用于在字符串中搜索searchedUrl: var input = '1234 url( test ) 5678'; var searchedUrl = 'test'; var regexpStr = "url\\(\\s*"+searchedUrl+"\\s*\\)"; var regex = new RegExp(regexpStr , 'i'); var match = input.match(regex); console.log(
searchedUrl
:
var input = '1234 url( test ) 5678';
var searchedUrl = 'test';
var regexpStr = "url\\(\\s*"+searchedUrl+"\\s*\\)";
var regex = new RegExp(regexpStr , 'i');
var match = input.match(regex);
console.log(match); // return an array
输出:
["url( test )", index: 5, input: "1234 url( test ) 5678"]
现在我想获得searchedUrl
的位置(在上面的示例中,它是test
在1234url(test)5678中的位置)
我该怎么做呢?你应该使用.exec,有很多关于子模式匹配的文档,你不需要索引。
在这种情况下,只要提供多一点信息就可以得到更好的答案。我不能怪你;我们被鼓励创建简单的测试用例,并删掉不相关的细节
但有一个重要的问题遗漏了:你打算如何处理该索引。与此同时,我们都在寻找错误的问题。:-)
我有一种感觉,有什么东西不见了;这就是我问你这件事的原因
正如您在评论中所提到的,您希望在输入字符串中找到URL,并以某种方式突出显示它,可以将其包装在
标记或类似标记中:
'1234 url( <b>test</b> ) 5678'
这比其他答案中的代码要简单一点,但它们中的任何一个都同样有效。这种方法的工作原理是将正则表达式锚定到字符串的开头(使用^
),并将所有字符放在URL前面(使用()
)。组字符串的长度,match[1]
,是您的索引
切片
一旦知道字符串中test
的起始索引,就可以使用.slice()
或其他字符串方法来剪切字符串并插入标记,可能使用类似以下代码:
var input = '1234 url( test ) 5678';
var url = 'test';
var regexpStr = "^(.*url\\(\\s*)"+ url +"\\s*\\)";
var regex = new RegExp( regexpStr , 'i' );
var match = input.match( regex );
var start = match[1].length;
// Wrap url in <b></b> tag by slicing and pasting strings
var output =
input.slice( 0, start ) +
'<b>' + url + '</b>' +
input.slice( start + url.length );
console.log( output );
这段代码在正则表达式中有三个组,一个用于捕获URL本身,URL前后的组用于捕获其他匹配文本,这样我们就不会丢失它。然后一个简单的.replace()
就完成了
通过这种方式,您不必担心任何字符串长度或索引。如果找不到URL,代码可以正常工作:它返回的输入字符串保持不变。据我所知,无法自动获取子匹配的偏移量,您必须使用RegExp的lastIndex
进行计算,或者由exec()
返回的匹配对象的索引
属性。根据您使用的组,您必须添加或减去子匹配前的组长度。但是,这意味着您必须将正则表达式的第一部分或最后一部分分组,直到您希望定位的模式为止
lastIndex
似乎仅在使用/g/
全局标志时起作用,它将在整个比赛后记录索引。因此,如果您希望使用lastIndex
,则需要从模式的末尾向后工作
有关exec()
方法的更多信息,请参阅此处:
以下简要说明了正在运行的解决方案:
var str = '---hello123';
var r = /([a-z]+)([0-9]+)/;
var m = r.exec( str );
alert( m.index + m[1].length ); // will give the position of 123
更新
这将适用于您的问题,具体如下:
var input = '1234 url( test ) 5678';
var searchedUrl = 'test';
var regexpStr = "(url\\(\\s*)("+searchedUrl+")\\s*\\)";
var regex = new RegExp(regexpStr , 'i');
var match = regex.exec(input);
然后,要获得子匹配偏移,可以使用:
match.index + match[1].length
match[1]
现在包含url(
(加两个空格),因为括号分组允许我们告诉内部偏移量
更新2
显然,如果在要定位的实际模式之前,在RegExp中有要分组的模式,事情会变得复杂一些。这只是将每个组长度相加的简单操作
var s = '~- [This may or may not be random|it depends on your perspective] -~';
var r = /(\[)([a-z ]+)(\|)([a-z ]+)(\])/i;
var m = r.exec( s );
要获得的偏移位置,取决于您的视角,您可以使用:
m.index + m[1].length + m[2].length + m[3].length;
显然,如果您知道RegExp的某些部分永远不会改变长度,那么您可以用硬编码的数值替换它们。但是,最好保持上述.length
检查,以防您或其他人更改表达式匹配的内容。JS没有直接的方法来获取子表达式的索引尝试/捕获组。但您可以使用一些技巧来解决此问题。例如:
var reStr = "(url\\(\\s*)" + searchedUrl + "\\s*\\)";
var re = new RegExp(reStr, 'i');
var m = re.exec(input);
if(m){
var index = m.index + m[1].length;
console.log("url found at " + index);
}
没有回答问题。他正在寻找子匹配的索引,已经使用match()
,并且已经显示它包含index
属性(结果不理想)。我已经研究了你提到的问题,但它没有回答我的问题。你们是对的,我将答案改为使用exec()而不是match()@RobbertvandenBogerd不幸的是,这并没有给潜艇位置either@m.buettner--这是个笑话吗?或者你真的不知道那有多粗鲁。我猜是前者。粗鲁?我认为如果你看到改进的余地,编辑别人的答案肯定是人们应该做的事情(参见,尤其是第二个答案)我认为,你最初的帖子包含了一个非常简洁的解决方案,但答案似乎与问题有点脱节,因为你的例子与OP的输入无关,所以我只是在留下你的文本的同时修改了这个例子,并添加了一些额外的解释,to使答案对OP.@m.buettner更有用是的,添加答案以改进它是好的。不表明原始答案是好的。正如你从我的编辑中所看到的——我最初计划作为第二次迭代——上面的方法是正确的。无论如何,如果代码中有问题,一个小的编辑是好的,但远远不够更礼貌的做法是先通知原始海报,或者让他们进行更改。这有点夸张,因为我只是更改了使用的输入和模式(没有您的解释)并为OP添加了一个小注释和链接,以便阅读捕获的实际情况。如果你计划更新与否,关键是,我不想打扰你,而是改进你的答案,以确保它得到支持和接受。我还可以发布我自己的答案,这在当时更适用于易读的
var reStr = "(url\\(\\s*)" + searchedUrl + "\\s*\\)";
var re = new RegExp(reStr, 'i');
var m = re.exec(input);
if(m){
var index = m.index + m[1].length;
console.log("url found at " + index);
}