我在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(match); // return an array
输出:
["url( test )", index: 5, input: "1234 url( test ) 5678"]
现在我想获得searchedUrl
的位置(在上面的示例中,它是test
中1234 url( test ) 5678
的位置。
我该怎么做?
答案 0 :(得分:2)
据我所知,不可能自动获得子匹配的偏移量,您必须自己使用RegExp的lastIndex
或index
进行计算。 exec()
返回的匹配对象的属性。根据您的使用情况,您必须添加或减去导致您的子匹配的组的长度。但是,这确实意味着您必须将正则表达式的第一部分或最后部分分组,直到您希望找到的模式。
lastIndex
似乎只在使用/g/
全局标志时发挥作用,它将在整个匹配后记录索引。因此,如果您希望使用lastIndex
,则需要从模式的末尾开始向后工作。
有关exec()
方法的详细信息,请参阅此处:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/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(
(加上两个空格),因为括号分组允许我们告诉内部偏移量。
显然,如果您希望在要查找的实际模式之前在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 );
要获得it depends on your perspective
的偏移位置,您将使用:
m.index + m[1].length + m[2].length + m[3].length;
显然,如果你知道RegExp的部分永远不会改变长度,你可以用硬编码数字值替换它们。但是,最好保留上述.length
检查,以防您 - 或其他人 - 更改您的表达式匹配的内容。
答案 1 :(得分:2)
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);
}
答案 2 :(得分:1)
这种情况下,提供更多信息会得到更好的答案。我不能因此而惹你生气;我们鼓励我们创建简单的测试用例并删除不相关的细节。
但是缺少一个重要的项目:你打算用该索引做什么。与此同时,我们都在追逐错误的问题。 : - )
我感觉有些东西不见了;这就是我问你的原因。
正如您在评论中提到的,您希望在输入字符串中找到该网址并以某种方式突出显示该网址,方法可能是将其打包在<b></b>
标记中,等等:
'1234 url( <b>test</b> ) 5678'
(如果你的意思是“亮点”,请告诉我。)
您可以使用字符索引来执行此操作,但使用正则表达式本身会更容易。
但是既然你问过,如果 需要索引,你可以用这样的代码得到它:
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;
这比其他答案中的代码简单一点,但其中任何一个都能同样有效。此方法的工作原理是将正则表达式锚定到包含^
的字符串的开头,并将所有字符放在具有()
的组中的URL之前。该组字符串match[1]
的长度是您的索引。
一旦知道字符串中test
的起始索引,就可以使用.slice()
或其他字符串方法来剪切字符串并插入标记,可能使用以下代码:
// 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 );
这肯定会奏效,但它确实是在努力做事。
另外,我遗漏了一些错误处理代码。如果没有匹配的网址怎么办? match
将undefined
,match[1]
将失败。但是,不要担心这一点,让我们看看如何在没有任何字符索引的情况下做到这一点。
让正则表达式为您完成工作。这就是整个事情:
var input = '1234 url( test ) 5678';
var url = 'test';
var regexpStr = "(url\\(\\s*)(" + url + ")(\\s*\\))";
var regex = new RegExp( regexpStr , 'i' );
var output = input.replace( regex, "$1<b>$2</b>$3" );
console.log( output );
此代码在正则表达式中有三个组,一个用于捕获URL本身,在URL之前和之后用于捕获其他匹配文本的组,因此我们不会丢失它。然后是一个简单的.replace()
,你已经完成了!
您不必担心任何字符串长度或索引。如果找不到URL,代码就会干净利落:它会使输入字符串保持不变。
答案 3 :(得分:-1)
您应该使用.exec,这里有关于mdn website
上子模式匹配的精彩文档