RegExp 的 exec()函数和 String 的 match()函数有什么区别?

如果我运行这个:

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

我明白了:

["a", "a"]

但如果我运行这个:

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

然后我得到了预期的结果:

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

有什么区别吗?

55339 次浏览

带有全局正则表达式的 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为您执行此操作,并丢弃捕获的组。

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

看这里: 执行官火柴

一张照片更好,你知道..。

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)之后返回,这不仅仅是匹配的模式。

如果您的正则表达式是全局的,并且您正在捕获,那么您必须使用 exec。

当只是匹配(不捕获)时,匹配非常有用。运行一次,它就会给出一个包含所有匹配项的数组。(尽管如果正则表达式不是全局的,那么 match 将显示匹配后跟捕获)

Exec 是在捕获时使用的,每次执行它都会提供匹配,然后是捕获。(仅当正则表达式不是全局的时候,match 的行为方式是给出完全匹配后跟捕获)。

Exec 的另一个用途是获取匹配项的索引或位置。当正则表达式有一个变量时,可以使用 .lastIndex并获得匹配的位置。正则表达式对象具有 .lastIndex,正则表达式对象就是对 .exec进行操作的对象。点匹配是在一个字符串上完成的,然后你就不能做正则表达式对象点最后索引

一个字符串,其中包含匹配函数,该函数被传递一个正则表达式。一个正则表达式,具有 exec 函数,并传递一个字符串

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

在不捕获和捕获时使用 match 是很好的你可以使用 exec,它更强大,因为它有利于捕获,但是如果你在捕获时使用 match,看到它显示捕获时正则表达式不是全局的,但是不显示捕获时正则表达式是全局的。

> "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,您可以获得匹配的“ index”

> 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-for not found)。

如果想进行扩展匹配,可以在捕获时使用它,但不能在正则表达式是全局的时候使用它,如果为此进行扩展匹配,那么数组的内容不是所有匹配,而是捕获之后的完全匹配。

。匹配()函数 str.match(regexp)将执行以下操作:

  • 如果有 匹配,它将返回:
    • 如果 regexp 中使用的 g标志 : 它将返回所有子字符串 (忽略捕获组)
    • 如果 regexp 中使用的 g标志是 没有,则返回与 regexp.exec(str)相同的值
  • 如果有 没有匹配,它将返回:
    • null

使用 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

没有 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)将执行以下操作:

  • 如果有 匹配,它将返回:
    • 如果 regexp 中使用的 g标志 : 它将返回下一个 N匹配的 (每次调用): [N_MatchedStr, N_Captured1, N_Captured2, ...]。如果 regexp 对象没有存储在变量中(它需要是同一个对象) ,那么 重要提示:将不会进入下一个匹配
    • 如果在 regexp 中使用的 g标志是 没有,那么它将返回与第一次且仅调用一次的 g标志相同的结果。
  • 如果有 没有匹配,它将返回:
    • null

. exec ()示例(使用 g标志存储 regexp + = 每次调用都会更改) :

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 标志时) , Exec ()将采用 x2到 x30之间的某个位置,然后是 string.match () :

因此,在这种情况下,使用“ new RegExp ()”方法。只有在需要全局正则表达式(即执行多次)时才应该使用 exec ()”。