请问有人能帮我理解正则表达式中的exec方法吗?

4
我发现exec方法最好的学习资料是《JavaScript编程精解》第9章:
正则表达式还有一个exec(执行)方法,如果没有找到匹配项,则返回null,否则返回包含匹配信息的对象。从exec返回的对象具有一个index属性,它告诉我们成功匹配开始的字符串位置。除此之外,该对象看起来像(实际上也是)由字符串数组组成,其第一个元素是匹配的字符串...."
这里都很好理解,但接下来会有点混淆:
当正则表达式包含用括号分组的子表达式时,与这些分组匹配的文本也将出现在数组中。整个匹配始终是第一个元素。
好吧,但...
下一个元素是第一组匹配的部分(其开头括号在表达式中首先出现),然后是第二组,以此类推。
var quotedText = /'([^']*)'/;
console.log(quotedText.exec("she said 'hello'"));
// → ["'hello'", "hello"]

我对这个例子中重复的“hello”感到困惑。我不明白为什么它会给我返回两个“hello”?

然后,以下内容概括了该主题:

“当一个组没有被完全匹配时(例如,跟随一个问号),它在输出数组中的位置将保持未定义。同样,当一个组被多次匹配时,只有最后一次匹配结果会出现在数组中。”

console.log(/bad(ly)?/.exec("bad"));
// → ["bad", undefined]
console.log(/(\d)+/.exec("123"));
// → ["123", "3"]

这个例子让我很困惑,希望你能给予解释。
非常感谢!

1
匹配(match)和捕获(capture)各返回一个。 - Avinash Raj
“我不明白为什么它会给我两个“hello”?”该表达式包含一个捕获组,无意中捕获了整个匹配。因此你会得到两次相同的值。 - Felix Kling
@FelixKling 表达式包含一个捕获组,无意中捕获了整个匹配 是错误的,首先匹配是 'hello' 2,捕获是 hello(不带引号) - Avinash Raj
1
@AvinashRaj:我的错,我错过了引号。看起来OP也可能是这样的 ;) - Felix Kling
1个回答

7
我不明白为什么会返回两个hello?
因为数组中的第一个条目是表达式的整体匹配结果,紧随其后的是表达式定义的任何捕获组的内容。由于该表达式定义了一个捕获组,所以会返回两个条目。整体匹配结果是带单引号的'hello',而捕获组中的内容是不带单引号的hello,因为在正则表达式中,只有hello在捕获组内(括号之间),而单引号在捕获组外。
让我们看一下/bad(ly)?/的示例:它的意思是"匹配bad,后面可以选择性地跟着ly,并在有时捕获ly"。因此,你会得到:
console.log(/bad(ly)?/.exec("bad"));
// -> ["bad", undefined]
//     ^      ^
//     |      +--- first capture group has nothing in it
//     +---------- overall match is "bad"
console.log(/bad(ly)?/.exec("badly"));
// -> ["badly", "ly"]
//     ^        ^
//     |        +- first capture group has "ly"
//     +---------- overall match is "badly"

假设我们将 ly 放在各自的捕获组中,并使它们都是可选的:
console.log(/bad(l)?(y)?/.exec("bad"));
// -> ["bad", undefined, undefined]
//     ^      ^          ^
//     |      |          +--- Nothing in the second capture group
//     |      +-------------- Nothing in the first capture group
//     +--------------------- Overall match is "bad"
console.log(/bad(l)?(y)?/.exec("badly"));
// -> ["badly", "l", "y"]
//     ^        ^    ^
//     |        |    +------- Second capture group has "y"
//     |        +------------ First capture group has "l"
//     +--------------------- Overall match is "badly"
console.log(/bad(l)?(y)?/.exec("badl"));
// -> ["badl", "l", undefined]
//     ^       ^    ^
//     |       |    +-------- Second capture group has nothing in it
//     |       +------------- First capture group has "l"
//     +--------------------- Overall match is "badl"
console.log(/bad(l)?(y)?/.exec("bady"));
// -> ["bady", undefined, "y"]
//     ^       ^          ^
//     |       |          +-- Second capture group has "y"
//     |       +------------- First capture group has nothing in it
//     +--------------------- Overall match is "bady"

非常简洁且信息量大!但是还有一件事... console.log(/(\d)+/.exec("123")); 在这个例子中,为什么在数字符号(\d)周围加上括号会有所不同?它们的作用是什么? - Anna
@Anna:在那个表达式中,它们基本上没有任何意义。没有它们的同样表达式,并使用完整匹配的结果,可以完成该表达式所做的一切。 - T.J. Crowder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接