2012-02-09 130 views
89

如果我运行此:RegExp的exec()函数和String的match()函数有什么区别?

/([^\/]+)+/g.exec('/a/b/c/d'); 

我得到这个:

["a", "a"] 

但是,如果我运行此:

'/a/b/c/d'.match(/([^\/]+)+/g); 

然后我得到的这个预期的结果:

["a", "b", "c", "d"] 

有什么区别?

+2

你用'exec'循环来获得所有的子选择。 – zzzzBov 2012-02-09 16:30:23

+2

请注意,不需要第二个'+',因为'match'将会返回所有的子表达式。 '.exec'每次只返回一个,所以它也不需要''''。 – pimvdb 2012-02-09 16:34:04

+3

最重要的是,像这两个加法的嵌套量词应该非常小心地使用,因为它们容易导致[灾难性的回溯](http://www.regular-expressions.info/catastrophic.html)。 – 2013-09-08 20:02:27

回答

89

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为您做这件事并丢弃捕获的组。

+15

我有一些东西要添加到这个答案,不应该把正则表达式文字放在while条件中,像这样'while(match = /[^\/]+/g.exec('/a/b/c/ d')'或者它会创建一个无限循环!正如MDN中明确指出的那样https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec – yeyo 2015-01-27 03:32:29

+3

@yeyo :更具体地说,它必须是相同的正则表达式对象,一个文字不会完成它 – Ryan 2015-01-27 05:12:20

21

/regex/.exec()只返回找到的第一个匹配,而"string".match()返回所有这些,如果您在正则表达式中使用g标志。

请看这里:exec,match

54

一幅画是更好的,你知道...

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)是匹配的模式后返回(例如:AA),它不只是匹配的模式。

+0

我知道我们不应该这样做,但这是一个很好的答案!我要保存它。 – Joe 2014-07-29 17:59:58

15

如果你的正则表达式是全局的,并且你正在捕获,那么你必须使用exec。匹配不会返回所有捕获。

匹配适用于匹配时(非捕获)。你运行它一次,它会给出所有匹配的数组。 (尽管如果正则表达式不是全局的,那么匹配将显示匹配,然后捕获)

Exec是您在捕获时使用的,每次执行时都会给出匹配,然后是捕获。 (只有在正则表达式不是全局的情况下,匹配的行为才是完全匹配,然后是捕获。

Exec的另一个用途是获取匹配的索引或位置。当你有一个正则表达式的变量时,你可以使用.lastIndex并获取匹配的位置。正则表达式对象具有.lastIndex,正则表达式对象就是您执行.exec的对象。点匹配是在一个字符串上完成的,然后您将无法再执行正则表达式对象点lastIndex

一个字符串,具有匹配函数,它传递了一个正则表达式。而一个正则表达式,具有exec功能,并通过一个字符串

exec你多次运行。匹配你运行一次

当不捕获时使用匹配是很好的,当捕获时可以使用更强大的exec,因为它有利于捕获,但是如果捕获时确实使用匹配,请参阅它捕获时显示正则表达式不是全局的,但当正则表达式是全局的时候不显示捕获。

> "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(请记住,正如你所看到的,用“索引”,它给出的“索引”实际上是第n次出现,它从1开始计数。通过减1来导出适当的索引。正如你所看到的,它给出了0 - lastIndex为0 - 对于未找到)。

如果你想扩展匹配,你可以在捕获时使用它,但是当正则表达式是全局的,而当你这样做的时候,那么数组的内容并不是全部匹配,但是完全匹配,然后是捕获。

相关问题