我目前正在研究正则表达式组。我无法完全理解本书中有关组的第一个示例。该书提供以下示例:
/(\S+) (\S*) ?\b(\S+)/
我知道这最多可以匹配三个单词(由空格组成的任何字符,除了空白),第二个单词和空格是可选的。
我很难理解的是边界条件在第三个单词的开头开始最后一组匹配的功能。
当包含三个单词时,是否包含它都没有区别。
只有两个词时,#2组和#3组之间存在差异
所以,我的问题如下
当有两个单词时,为什么\b
的存在会导致 group#2 成为预期的空字符串,但是如果不存在,则会导致 group#2 < / strong>包含第二个单词减去最后一个字母,而 group#3 包含第二个单词的最后一个字母?
答案 0 :(得分:2)
当有两个单词时,为什么\ 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
在第一个模式中,如果字符串中只有两个单词,则最后一组之前的单词边界可确保第二组不匹配任何字符-而不是回溯到最后一组之前的 字符,它必须一直备份直到找到单词边界:
原始模式可能有一点缺陷-\b
匹配单词边界,但并非每个非空格字符都是单词字符-(可能不受欢迎)matches foo it's
it'
进入第二组,而s
进入第三组。
答案 1 :(得分:1)
差异来自第二组(\S*)
-它将捕获任意数量的非空白字符。因此,当您有两个单词但三个组中最后一个是(\S+)
时-匹配至少一个非空白字符,则正则表达式引擎将尝试同时满足第2组和第3组。
请记住,它与某个模式匹配,并且您没有告诉它 not 这样匹配。因此,它完成了最低限度的工作-第二组\S*
最初将与抓取brown
的所有内容匹配-模式的下一部分是一个可选空格,该空格将传递,然后到达最后一组{{ 1}},并且由于它具有强制性字符,因此第二个匹配项将逐个释放匹配项,直到满足第3组为止。
您可以在这里看到-我将第三组定义为至少具有两个必需字符,因此只能得到两个:
\S+
当您改为在模式中添加单词边界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)
时,第2组中的任何字符和都不能满足后面的条件-当正则表达式使用字符时,其余部分模式只会从该字符开始继续,因此您将无法进行匹配,例如,第2组匹配\b
,然后有一个单词边界,后跟b
。满足rown
的唯一方法是:
(\S+) (\S*) ?\b(\S+)
the