javascript 正则表达式 - 组

javascript regular expressions - groups

我目前正在研究正则表达式组。我无法完全理解书中第一个示例在组下的介绍。书中给出了以下示例:

/(\S+) (\S*) ?\b(\S+)/

我知道这最多匹配三个单词(由除白色 space 之外的任何字符组成),其中第二个单词和 space 是可选的。

我不太理解的是边界条件的作用是从第三个单词开始匹配最后一组。

当有三个字时 收不收无所谓

当只有两个单词时,第 2 组和第 3 组之间存在差异

那么,我的问题如下

当有两个词时,为什么 \b 的存在导致 group#2 像预期的那样是一个空字符串,但是当不存在时导致 group #2 包含第二个单词减去最后一个字母和 group #3 包含第二个单词的最后一个字母?

When there are two words, why is the presence of \b causing group#2 to be an empty string as expected

查看第一组和第三组 - (\S+),它们 必须 包含字符。当有两个单词时,这两个单词必须进入第一组和第三组-第二组,因为它用*重复,不会消耗任何字符,并且是空字符串。

but when not present causes group #2 to contain the second word minus the last letter and group #3 to contain the last letter of the second word?

当模式是

(\S+) (\S*) ?(\S+)

一旦引擎匹配了第一个词,引擎就会开始尝试匹配第二个词。所以如果输入是 foo bar,我们可以考虑模式 (\S*) ?(\S+) 如何作用于 bar.

引擎首先尝试使用 \S* 消耗字符串中的所有剩余字符。这失败了,因为最后一组需要包含至少一个字符,所以引擎备份一个步骤,并让 \S* 组匹配除最后一个字符之外的所有字符。这导致匹配成功,因为最后一个字符之前的位置确实匹配 \s?(\S+).

你可以在这里直观地看到这个过程:

https://regex101.com/r/RAkEOt/1/debugger

在第一个模式中,最后一组之前的单词边界确保第二组不匹配任何字符,以防字符串中只有两个单词 - 而不是回溯到之前的 最后一个个字符,它必须一直备份直到找到一个单词边界:

原始模式可能略有缺陷 - \b 匹配 单词边界 ,但并非每个 non-space 字符都是单词字符 - 它(可能不受欢迎的)matches foo it's 其中 it' 进入第二组,s 进入第三组。

不同之处在于第二组 (\S*) - 它将捕获任意数量的 non-whitespace 个字符。因此,当您有两个单词但三个组,其中最后一个是 (\S+) - 匹配 至少一个 non-whitespace 字符时,正则表达式引擎将尝试同时满足这两个条件第 2 组和第 3 组。

请记住,它正在匹配一个模式,而您并没有告诉它不要那样匹配。因此它做了最少的必要工作——第二组的 \S* 最初将匹配所有抓取的 brown - 模式的下一部分是可选的 space,它通过,然后到达最终组\S+,由于有必填字符,第二场会逐一放出匹配,直到满足第3组。

你可以在这里看到这个 - 我已经将第三组定义为至少有两个强制字符,因此它只有两个:

let [ , group1, group2, group3] = "the brown".match(/(\S+) (\S*) ?(\S{2,})/);

console.log("group 1:", group1)
console.log("group 2:", group2)
console.log("group 3:", group3)

当您将单词边界 \b 添加到模式时,您不能让第 2 组有任何字符 满足后面的条件 - 当正则表达式使用一个character 模式的其余部分只会从该字符开始继续,因此你不能有,例如第 2 组匹配 b 然后有一个单词边界后跟 rown。满足(\S+) (\S*) ?\b(\S+)的唯一方法如下:

  • 组 1 匹配 the
  • space字符匹配
  • 第 2 组什么都不匹配,这是可以接受的,因为它可以匹配任何数量,包括零
  • 可选的 space 匹配零 spaces
  • 有词界
  • 第 3 组消耗了剩余的字母 - brown