关于正则的一个小问题?

关于正则的一个小问题
/#\/((\w)+)/.exec("/a-web/#/abc?")
返回值是
 ['#/abc', 'abc', 'c', index: 7, input: '/a-web/#/abc?', groups: undefined]

数组第二项是匹配项(\w+) 返回 'abc'
数组的第三项 返回值 'c'怎么理解啊

没啥尝试

阅读 1.8k
avatarAI BotBETA

在正则表达式中,当你使用括号(无论是捕获组还是非捕获组)时,它们会捕获匹配到的内容。在你的正则表达式 /#\/((\w)+)/ 中,存在两个层次的括号:

  1. 外层括号 ((\w)+):这是一个捕获组,它捕获整个 \w+ 匹配到的内容。\w+ 匹配一个或多个单词字符(字母、数字或下划线)。
  2. 内层括号 (\w):虽然这个括号在技术上是一个捕获组,但由于它紧跟在 + 量化符之后,它的行为可能与你预期的不同。在正则表达式中,+ 量化符作用于其前面的元素(这里是 \w),意味着它会尝试匹配一个或多个 \w。然而,由于内层括号的存在,+ 实际上是在说“匹配一个或多个 \w,但每次只捕获最后一个 \w”。这是因为正则引擎在尝试匹配多个 \w 时,会不断更新这个内层捕获组的内容,直到 \w+ 匹配完成,此时内层捕获组只保留最后一次匹配的内容。

在你的例子中,/#\/((\w)+)/ 匹配字符串 "/a-web/#/abc?" 中的 #/abc 部分。

  • 外层捕获组 ((\w)+) 捕获了整个 abc,因为它匹配了 \w+(即一个或多个单词字符)。
  • 内层捕获组 (\w) 在匹配过程中不断更新其内容,但只保留最后一次匹配的内容,即 c

因此,当你使用 .exec() 方法时,返回的数组包含:

  • 第一个元素是整个匹配项 #/abc
  • 第二个元素是外层捕获组匹配的内容 abc
  • 第三个元素是内层捕获组匹配的内容 c,这是因为在 \w+ 匹配 abc 的过程中,内层捕获组只保留了最后一次匹配的内容。

如果你不希望出现这种情况,可以移除内层的括号,只保留外层的捕获组,即使用正则表达式 /#\/(\w+)/。这样,你就只会得到一个捕获组,它捕获整个 \w+ 匹配到的内容。

5 个回答

机器人回答的很机智,我只能点个赞了
image.png

第一项是整个正则表达式所匹配到的文本

#\/((\w)+) -> #/abc

之后的每一项依次是正则表达式的分组

((\w)+) -> abc

(\w) -> c

因为有多个括号,所以被认为是多个 捕获组正则表达式 - JavaScript | MDN
具体的解释AI回答已经足够清晰了。

如果匹配成功,exec() 方法返回一个数组,并更新正则表达式对象的 lastIndex 属性。完全匹配成功的文本将作为返回数组的第一项,从第二项起,后续每项都对应一个匹配的捕获组。


可以通过一些正则表达式可视化的小工具来检查是否可以简化正则表达式。
图片.png

比如你的这个规则其实就可以简化成 /#\/\w+/ 效果是一样的。
图片.png

小括号在正则表达式的含义为分组,分组通常有三种用途:

  • 作为一个整体进行匹配
  • 限定选择结构范围
  • 后向引用或提取

举例说明:

  • (ab)?ab 这两个字母进行分组,后面的?表示这个分组至多出现1次,不会匹配单独的ab,必须成组出现
  • (aaa|bbb),通常|这种选择结构出现的时候,要配合分组括号限定匹配的范围。以这个例子为例,代表可以匹配aaa或者bbb,即使单个字符选择结构通常也得加上分组括号 (a|b)
  • (\w+)\1,这个结构代表捕获到的第一组进行重复,这里的\1就是后向引用,代表引用前面第一个分组匹配到的内容,例如会匹配到aa, bb, abab, abcabc等等

你的用例其实就跟第三种的用例差不多,通过分组之后可以将分组内容进行提取,也就是groups返回值的内容,会将所有小括号匹配到的内容按顺序生成array

/#\/((\w)+)/.exec("/a-web/#/abc?")

  • '#abc'
    这是整个正则表达式匹配的字符串,代表正则表达式中的完整匹配部分:#/abc。这个值是由#\/((\w)+)匹配到的
  • 'abc'
    这是第一个捕获组((\w)+)的匹配。
  • 'c'
    这是第二个捕获组(\w)的匹配结果。虽然使用了(\w)+,但它是嵌套在外部捕获组中的,所以只返回最后一个字符。
推荐问题
宣传栏