4

我在 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(在上面的例子中,它是 testin的位置1234 url( test ) 5678

我怎样才能做到这一点?

4

5 回答 5

2

据我所知,无法自动获取子匹配的偏移量,您必须使用lastIndexRegExp 或indexexec(). 根据您使用的方式,您必须添加或减去导致子匹配的组的长度。但是,这确实意味着您必须将正则表达式的第一部分或最后一部分分组,直到您希望找到的模式。

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((加上两个空格),因为括号分组允许我们告诉内部偏移量。

更新 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 );

要获得您的偏移位置,it depends on your perspective请使用:

m.index + m[1].length + m[2].length + m[3].length;

显然,如果您知道 RegExp 具有永远不会改变长度的部分,您可以用硬编码的数值替换这些部分。但是,最好保留上述.length检查,以防您或其他人更改您的表达式匹配的内容。

于 2013-06-11T08:55:36.857 回答
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);
}
于 2013-06-11T08:57:58.133 回答
1

你不需要索引。

在这种情况下,提供更多信息会得到更好的答案。我不能因此而责怪你;我们鼓励创建简单的测试用例并删除不相关的细节。

但是缺少一个重要的项目:您计划对该索引做什么。与此同时,我们都在追逐错误的问题。:-)

我觉得少了点什么;这就是我问你的原因。

正如您在评论中提到的,您希望在输入字符串中找到 URL 并以某种方式突出显示它,也许通过将其包装在<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 );

这肯定会奏效,但它确实是在以艰难的方式做事。

另外,我遗漏了一些错误处理代码。如果没有匹配的 URL 怎么办?match将会undefinedmatch[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,则代码可以正常工作:它会返回未更改的输入字符串。

于 2013-06-11T08:55:22.573 回答
0

您可以将'd'标志添加到正则表达式,以便为子字符串匹配生成索引。

const input = '1234 url(  test  ) 5678';
const searchedUrl = 'test';

const regexpStr = "url\\(\\s*("+searchedUrl+")\\s*\\)"; 
const regex = new RegExp(regexpStr , 'id');

const match = regex.exec(input).indices[1]
console.log(match); // return [11, 15] 
于 2021-09-20T08:17:06.410 回答
-1

您应该使用 .exec,在mdn 网站上有很多关于子模式匹配的文档

于 2013-06-11T08:51:02.637 回答