如果我运行这个:
/([^\/]+)+/g.exec('/a/b/c/d');
我得到了这个:
["a", "a"]
但是如果我运行这个:
'/a/b/c/d'.match(/([^\/]+)+/g);
然后我得到了这个预期结果:
["a", "b", "c", "d"]
有什么不同之处?
如果我运行这个:
/([^\/]+)+/g.exec('/a/b/c/d');
我得到了这个:
["a", "a"]
但是如果我运行这个:
'/a/b/c/d'.match(/([^\/]+)+/g);
然后我得到了这个预期结果:
["a", "b", "c", "d"]
有什么不同之处?
exec
与全局正则表达式一起使用时,应该放在循环中使用,因为它仍然会检索所有匹配的子表达式。所以:
var re = /[^\/]+/g;
var match;
while (match = re.exec('/a/b/c/d')) {
// match is now the next match, in array form.
}
// No more matches.
String.match
可以为您执行此操作,并且会丢弃捕获的组。
while(match = /[^\/]+/g.exec('/a/b/c/d')
,否则会创建一个无限循环!根据MDN上明确的说明https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec。 - yeyonew RegExp("pattern")
和/pattern/
有不同的含义。 - Robert一张图片胜过千言万语...
re_once = /([a-z])([A-Z])/
re_glob = /([a-z])([A-Z])/g
st = "aAbBcC"
console.log("match once="+ st.match(re_once)+ " match glob="+ st.match(re_glob))
console.log("exec once="+ re_once.exec(st) + " exec glob="+ re_glob.exec(st))
console.log("exec once="+ re_once.exec(st) + " exec glob="+ re_glob.exec(st))
console.log("exec once="+ re_once.exec(st) + " exec glob="+ re_glob.exec(st))
看到区别了吗?
注意:为了强调,需要注意捕获组(例如:a,A)是在匹配的模式(例如:aA)之后返回的,而不仅仅是匹配的模式本身。
> "azb".match(/a(z)b/);
[ "azb", "z" ]
> "azb".match(/a(z)b/g);
[ "azb" ]
>
另外一件事是,如果您使用exec,请注意它是在正则表达式上调用的,如果您为正则表达式使用了变量,则具有更大的控制力。
当您不使用正则表达式的变量时,无法获取匹配项,因此在使用exec时请使用正则表达式的变量。
> /./g.exec("abc")
[ "a" ]
> /./g.exec("abc")
[ "a" ]
> /./g.exec("abc")
[ "a" ]
>
> /[a-c]/g.exec("abc")
[ "a" ]
> /[a-c]/g.exec("abc")
[ "a" ]
>
> var r=/[a-c]/g
> r.exec("abc")
[ "a" ]
> r.exec("abc")
[ "b" ]
> r.exec("abc")
[ "c" ]
> r.exec("abc")
null
>
使用 exec 方法,您可以获取匹配项的“索引”
> var r=/T/g
> r.exec("qTqqqTqqTq");
[ "T" ]
> r.lastIndex
2
> r.exec("qTqqqTqqTq");
[ "T" ]
> r.lastIndex
6
> r.exec("qTqqqTqqTq");
[ "T" ]
> r.lastIndex
9
> r.exec("qTqqqTqqTq");
null
> r.lastIndex
0
>
因此,如果您需要索引或捕获,则使用exec(请记住,如您所见,对于“index”,它给出的“index”实际上是第n个出现,它从1开始计数。因此,您可以通过减去1来得出正确的索引。如您所见,对于未找到的情况,它会给出0 - lastIndex为0)。
如果您想要进行伸展匹配,可以在捕获时使用它,但不适用于正则表达式为全局时,并且当您为其执行时,数组的内容并不是所有匹配项,而是完整的匹配项以及其后的捕获内容。
r.lastIndex
的工作方式是理解exec
和match
之间差异的关键因素。 - runsun"a,b,c,aa,bb,cc".match(/(\w+)/g)
,它显示了所有的匹配项,而恰好你捕获了每一个匹配项,所以如果它要显示所有的捕获,它看起来会完全相同(续)。 - barlop.match() 函数 str.match(regexp)
的功能如下:
g
标志:它将返回所有子字符串(忽略捕获组)g
标志:它将返回与 regexp.exec(str)
相同的结果null
使用 .match() 的示例,其中使用了 g
标志:
var str = "qqqABApppabacccaba";
var e1, e2, e3, e4, e5;
e1 = str.match(/nop/g); //null
e2 = str.match(/no(p)/g); //null
e3 = str.match(/aba/g); //["aba", "aba"]
e4 = str.match(/aba/gi); //["ABA", "aba", "aba"]
e5 = str.match(/(ab)a/g); //["aba", "aba"] ignoring capture groups as it is using the g flag
.match()函数不带g
标记相当于.exec()函数:
e1=JSON.stringify(str.match(/nop/))===JSON.stringify(/nop/.exec(str)); //true
//e2 ... e4 //true
e5=JSON.stringify(str.match(/(ab)a/))===JSON.stringify(/(ab)a/.exec(str)); //true
.exec()函数regexp.exec(str)
的作用:
g
标记,那么每次调用时都将返回下一个N
个匹配项和对应的捕获组结果[N_MatchedStr, N_Captured1, N_Captured2, ...]
。请注意:重要提示:如果正则表达式对象没有存储在变量中(需要是同一个对象),它不会进入下一个匹配项。g
标记,它将返回与第一次调用并且只执行一次且使用了g
标记的相同结果。null
.exec()的示例(存储的正则表达式+使用g
标记=每次调用时都会改变):
var str = "qqqABApppabacccaba";
var myexec, rgxp = /(ab)a/gi;
myexec = rgxp.exec(str);
console.log(myexec); //["ABA", "AB"]
myexec = rgxp.exec(str);
console.log(myexec); //["aba", "ab"]
myexec = rgxp.exec(str);
console.log(myexec); //["aba", "ab"]
myexec = rgxp.exec(str);
console.log(myexec); //null
//But in this case you should use a loop:
var mtch, myRe = /(ab)a/gi;
while(mtch = myRe.exec(str)){ //infinite looping with direct regexps: /(ab)a/gi.exec()
console.log("elm: "+mtch[0]+" all: "+mtch+" indx: "+myRe.lastIndex);
//1st iteration = elm: "ABA" all: ["ABA", "AB"] indx: 6
//2nd iteration = elm: "aba" all: ["aba", "ab"] indx: 12
//3rd iteration = elm: "aba" all: ["aba", "ab"] indx: 18
}
.exec()方法在每次调用时不会改变的示例:
var str = "qqqABApppabacccaba", myexec, myexec2;
//doesn't go into the next one because no g flag
var rgxp = /(a)(ba)/;
myexec = rgxp.exec(str);
console.log(myexec); //["aba", "a", "ba"]
myexec = rgxp.exec(str);
console.log(myexec); //["aba", "a", "ba"]
//... ["aba", "a", "ba"]
//doesn't go into the next one because direct regexp
myexec2 = /(ab)a/gi.exec(str);
console.log(myexec2); //["ABA", "AB"]
myexec2 = /(ab)a/gi.exec(str);
console.log(myexec2); //["ABA", "AB"]
//... ["ABA", "AB"]
有时候,regex.exec() 的执行时间比 string.match() 要长得多。
值得一提的是,如果 string.match() 和 regex.exec() 的结果相同(例如不使用 \g 标志),则 regex.exec() 的执行时间将在 string.match() 的 2 到 30 倍之间:
因此,在这种情况下,只有当您需要全局正则表达式(即执行多次)时,才应该使用 "new RegExp().exec()" 的方法。
match chain:
some_string.replace(expr).match(expr); //etc...
With exec:
let exec = new RegExp(regexp );
for(for expression ){
exec.(string );
//other body of FOR
}
exec
循环获取所有的子选择。 - zzzzBov+
不必要,因为match
已经返回了所有的子表达式。.exec
每次只返回一个,因此也不需要那个+
。 - pimvdb