我正在尝试在JavaScript中懒惰匹配一个组,但是我没有像我期望的那样工作。
"/1000/2000/".match("(?:/)(.*?)(?:/)$")
这就是我所拥有的以及我相信这个正则表达式将会做的事情:
/
字符/
个字符之间的任何内容,但最短匹配/
字符那应该返回2000
,但它会返回1000/2000
。那是为什么?
答案 0 :(得分:2)
(?:)
是一个非捕获组 - 它仍然包含匹配中的内容,但不会为()
括号创建组匹配。
分解正则表达式:
(?:/)
将匹配字符串中的第一个斜杠(但括号不会创建组。)(.*?)
将匹配任何字符的零或多个,直到模式后续部分的第一个匹配(并且括号创建单独的捕获组)(?:/)$
将匹配斜杠,紧跟字符串结尾(并且括号不会创建组)。因此第一部分将匹配第一个字符,最后一部分将匹配最后一个字符,中间位将匹配其他匹配所需的数量(即中间的所有内容)。
作为替代方案,这将匹配两个斜杠之间的最后一个字符串,其中最后一个斜杠位于单词的末尾:
"/1000/2000/".match("[^/]*(?=/$)")
答案 1 :(得分:2)
将字符串与正则表达式匹配时,引擎会从左到右尝试每个位置,直到找到匹配项。
由于字符串是从左向右扫描的,(?:/)(.*?)(?:/)$
可以在输入字符串/1000/2000/
的索引0处找到匹配项。
延迟量词仅影响重复尝试的顺序。它将尝试空字符串,然后重复一次,两次,3次等。由于.
匹配除行终止符之外的任何内容,并且从左到右尝试字符串,所以匹配整个/1000/2000/
。
顺便说一下,虽然它通常说.*?
匹配可能的字符数最少,但正确的定义是 lazy量词会尝试扩展 atom (在这种情况下是.
)可能的次数最少,因此续集(在本例中为(?:/)$
)可以匹配。 < / p>
如其他答案中所述,解决方案是通过将/
替换为.
来限制[^/]
之间的允许字符集。更改字符类后,您可以使用贪婪或惰性量词,因为语法已变得明确,因此搜索顺序不会影响最终结果。
答案 2 :(得分:1)
?:X
模式是JavaScript中的match but do not capture指令,因此我们看到以下模式:
(?:/)(.*?)(?:/)$
转换为:
/
(某处),但不捕获/
后跟字符串结束,但不捕获因此,第一个/
被匹配并且提示被遗忘,然后我们匹配set(2),它为(?:/)$
后跟的“任何字符”尝试非贪婪匹配。由于最后一部分仅匹配输入字符串末尾的斜杠,因此我们找到并忽略第一个和最后一个/
,这会留下1000/2000
。
如果您想要1000
,那么根本没有理由打扰regexp:
// get some input
var s = "/1000/2000/";
// split on slashes
var t = s.split('/');
// filter out empties
t = t.filter(function(a) { return !!a ; });
// convert to ints, because why not. Note that even regexp will
// yield strings, so you still have to do this if you do use regexp.
t = t.mapfunction(a) { return parseInt(a,10); });
// results are....
console.log(t.join(", ")); // => "1000, 2000"
如果您正在寻找“斜杠之间的东西”,只需寻找不是斜线的东西:
"/1000/2000/".match(/([^\/]+)/g) // => Array [ "1000", "2000" ]
答案 3 :(得分:0)
试试这个,但它并不是最优雅的解决方案:
'/1000/2000/'.match(/(?!\/)\d+(?=\/$)/);