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

Jus*_*tin 112 javascript regex

如果我运行这个:

/([^\/]+)+/g.exec('/a/b/c/d');
Run Code Online (Sandbox Code Playgroud)

我明白了:

["a", "a"]
Run Code Online (Sandbox Code Playgroud)

但如果我运行这个:

'/a/b/c/d'.match(/([^\/]+)+/g);
Run Code Online (Sandbox Code Playgroud)

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

["a", "b", "c", "d"]
Run Code Online (Sandbox Code Playgroud)

有什么不同?

Ry-*_*Ry- 109

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.
Run Code Online (Sandbox Code Playgroud)

String.match 为您做到这一点并丢弃捕获的组.

  • 我有一些东西要添加到这个答案中,不应该将正则表达式文字放在while条件中,比如这个`while(match = /[^\/]+/g.exec('/a/b/c/d) ')`或者它会创建一个无限循环!正如它在MDN中明确说明的那样https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec (32认同)
  • @yeyo:更具体地说,它必须是相同的正则表达式对象.文字不能实现这一点. (7认同)

geo*_*org 69

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

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))
Run Code Online (Sandbox Code Playgroud)

看到不同?

注意:要突出显示,请注意在匹配的模式(例如:aA)之后返回捕获的组(例如:a,A),它不仅仅是匹配的模式.


Ale*_*ian 28

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

看到这里:exec,匹配.


bar*_*lop 22

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

匹配在匹配(不捕获)时非常有用.你运行一次,它给出了所有匹配的数组.(虽然如果正则表达式不是全局的,那么匹配将显示匹配后跟捕获)

Exec是你捕获时使用的,每次执行时都会给出匹配,然后是捕获.(匹配将以提供完全匹配然后捕获的方式运行,仅当正则表达式不是全局时).

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

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

执行你多次运行.匹配你运行一次

不捕获时使用匹配是好的,捕获时你可以使用更强大的exec,因为它有利于获取捕获,但如果你在捕获时使用匹配,看看它在正则表达式不是全局时显示捕获,但不是当正则表达式是全局时,显示捕获.

> "azb".match(/a(z)b/);
[ "azb", "z" ]

> "azb".match(/a(z)b/g);
[ "azb" ]
>
Run Code Online (Sandbox Code Playgroud)

另一件事是,如果你使用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
>
Run Code Online (Sandbox Code Playgroud)

使用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
>
Run Code Online (Sandbox Code Playgroud)

因此,如果你想要索引或捕获,那么使用exec(请记住,正如你所看到的,使用"索引",它给出的"索引"实际上是第n次出现,它从1开始计数.所以你可以得到正确的通过减去1来索引.正如你所看到的,它给0 - lastIndex为0 - 未找到).

如果你想拉伸匹配,你可以在捕获时使用它,但是当正则表达式是全局的时候就不能使用它,当你为它做的时候,那么数组的内容不是所有的匹配,而是完整的匹配后跟捕获.


aja*_*221 5

.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
Run Code Online (Sandbox Code Playgroud)

.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
Run Code Online (Sandbox Code Playgroud)

.exec()函数regexp.exec(str)将执行以下操作:

  • 如果匹配的,则回复:
    • 如果在则表达式中使用了该g标志:它将返回(每次调用时):下一个匹配项:。重要提示:如果regexp对象未存储在变量中(它必须是同一对象),则不会前进到下一个匹配项[N_MatchedStr, N_Captured1, N_Captured2, ...]N
    • 如果该g标志在正则表达式中使用:它将返回与具有g标志且第一次被调用且仅被调用一次相同的结果。
  • 如果没有匹配,它将返回:
    • null

.exec()的示例(存储的regexp +使用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
}
Run Code Online (Sandbox Code Playgroud)

的实例.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"]
Run Code Online (Sandbox Code Playgroud)