【问题标题】:javascript regular expressions - groupsjavascript 正则表达式 - 组
【发布时间】:2019-10-18 15:07:18
【问题描述】:

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

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

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

我难以理解的是边界条件的功能是在第三个单词的开头开始最后一组的匹配。

当有三个单词时,是否包含没有区别。

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

所以,我的问题如下

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

【问题讨论】:

标签: javascript regex regex-group


【解决方案1】:

当有两个单词时,为什么\b的存在导致group#2如预期的那样是一个空字符串

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

但是当不存在时会导致组#2 包含第二个单词减去最后一个字母,而组#3 包含第二个单词的最后一个字母?

当模式是

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

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

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

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

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

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

原始模式可能有一些缺陷 - \b 匹配 单词边界,但并非每个非空格字符都是单词字符 - 它(可能不受欢迎)matches foo it's @987654338 @ 进入第二组,s 进入第三组。

【讨论】:

    【解决方案2】:

    区别来自第二组(\S*) - 它将捕获任意数量的非空白字符。因此,当您有两个单词但三个组,其中最后一个是 (\S+) - 匹配 至少一个 非空白字符时,正则表达式引擎将尝试同时满足第 2 组和第 3 组。

    请记住,它正在匹配一个模式,而您没有告诉它要像那样匹配。因此,它完成了必要的最少工作——第二组的\S* 最初将匹配所有抓取brown 的东西——模式的下一部分是一个可选空间,它通过,然后到达最后一组\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 有任何字符 并且 满足后面的条件 - 当正则表达式使用一个字符时,模式的其余部分将仅从该字符开始继续,因此您不能让例如第 2 组匹配b,然后有一个单词边界,后跟rown。满足(\S+) (\S*) ?\b(\S+) 的唯一方法是:

    • 第 1 组匹配 the
    • 空格字符匹配
    • 组 2 不匹配任何内容,这是可以接受的,因为它可以匹配任何数量,包括零
    • 可选空格匹配零个空格
    • 有单词边界
    • 第 3 组消耗剩余的字母 - brown

    【讨论】:

      猜你喜欢
      • 2012-03-10
      • 2012-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多