Java 理解量词

Java 理解量词,java,regex,quantifiers,Java,Regex,Quantifiers,我正在经历一场灾难 贪婪量词、不情愿量词和所有格量词之间存在差异 我无法理解到底有什么区别 解释如下: Enter your regex: .*foo // greedy quantifier Enter input string to search: xfooxxxxxxfoo I found the text "xfooxxxxxxfoo" starting at index 0 and ending at index 13. Enter your regex: .*?foo // r

我正在经历一场灾难

贪婪量词、不情愿量词和所有格量词之间存在差异

我无法理解到底有什么区别

解释如下:

Enter your regex: .*foo  // greedy quantifier
Enter input string to search: xfooxxxxxxfoo
I found the text "xfooxxxxxxfoo" starting at index 0 and ending at index 13.

Enter your regex: .*?foo  // reluctant quantifier
Enter input string to search: xfooxxxxxxfoo
I found the text "xfoo" starting at index 0 and ending at index 4.
I found the text "xxxxxxfoo" starting at index 4 and ending at index 13.

Enter your regex: .*+foo // possessive quantifier
Enter input string to search: xfooxxxxxxfoo
No match found.
第一个示例使用贪婪量词。*查找“任何东西”,零次或多次,后跟字母“f”“o”“o”。因为量词是贪婪的,所以表达式的.*部分首先吃掉整个输入字符串。此时,整个表达式不可能成功,因为最后三个字母(“f”“o”“o”)已被使用。因此,匹配者一次慢慢地后退一个字母,直到最右边出现的“foo”被反刍,此时匹配成功,搜索结束

然而,第二个例子是不情愿的,因此它首先消耗“无”。因为“foo”不出现在字符串的开头,所以它被迫吞下第一个字母(“x”),这将在0和4处触发第一个匹配。我们的测试工具将继续这个过程,直到输入字符串耗尽为止。它在4和13处找到另一个匹配项


第三个例子找不到匹配项,因为量词是所有格。在本例中,整个输入字符串由。*+使用,不留下任何剩余内容来满足表达式末尾的“foo”。使用所有格量词来表示你想抓住所有东西而不后退的情况;在没有立即找到匹配项的情况下,它将优于等价的贪婪量词。

懒惰(不情愿)和贪婪情况之间的主要区别在于回溯结构的行为,而所有格的行为太过激进

  • Lazy case将始终在单个匹配后将匹配引擎的焦点交给正则表达式中的下一个操作符。如果下一个操作符失败,回溯结构将强制重复惰性大小写,这将持续到操作符或目标文本结束;例如,在您的示例中,在每次成功匹配后传递到char
    f
    的匹配,因此每当您有一个
    foo
    短语时,您都会得到一个匹配,这就是为什么我们从它的使用中得到多个匹配
*?foo

xfooxxxxxxfoo
开始时,lazy case将成功匹配
x
(成功空匹配后),并将焦点传递给下一个操作符
foo
是正则表达式的一部分,由于它出现在
x
之后,我们得到了这个片段的匹配,字符串的第二部分也是这样

  • 贪婪案例则相反,将继续其匹配直到失败,从不将焦点传递给下一个操作符,只有当匹配失败时回溯才会生效,下一个操作符将从反向匹配
*foo

xfooxxxxxfoo
当贪婪的情况出现在这一点(最后一个字符)时,匹配将失败,因为我们无法匹配正则表达式的
foo
部分。然后,回溯将强制贪婪案例回溯其步骤,并强制执行下一个操作符
foo
,类似于懒惰案例

xfooxxxxxxfoo
此时,
foo
部分将获得成功匹配,从而以整个字符串的成功匹配结束

  • 所有格与贪心格非常相似,除了最后一部分,匹配失败导致了
    回溯
    ,这不是所有格的情况。如果它能被匹配,它将拥有并将在这个过程中牺牲比赛的成功。如果它在匹配字符时失败,那么焦点将传递给正则表达式的下一个操作符
*+foo

xfooxxxxxfoo
与贪婪格类似,我们已经到达了字符串的末尾,但所有格仍然可以匹配它,因此不会将火炬传递到
回溯
结构,并将导致匹配失败

一般规则 理解量词
*
+
(分别为“零或一”、“零或多”、“一或多”)的基本知识

  • 我们说,如果一个量词试图阐述尽可能多的字符,它就是贪婪的
  • 我们说,如果一个量词试图尽可能少地阐述一些字符,那么它就是不情愿的
  • 如果一个量词是贪婪的并且不允许回溯,我们说它是所有格的
只有了解正则表达式解析器的工作原理,才能理解“回溯”的含义(请参见下面的“动态示例”)

个案解释
  • :首先出现测试1,然后出现0;如果您发现了一个匹配项,然后需要放弃它,您可以这样做
  • ??
    :首先测试0次,然后测试1次
  • ?+
    :首先出现测试1,然后出现0;如果您发现了一个匹配项,然后需要将其丢弃,则无法执行该操作
  • *
    :尝试获取尽可能多的事件(甚至0);如果发现了N个实例,然后需要放弃(其中的一些),则可以从最后一个实例开始执行此操作
  • *?
    :尽量减少出现次数(即使是0次)
  • *+
    :尝试获取尽可能多的事件(甚至0);如果您发现了N个实例,然后需要丢弃(其中的一部分),则无法执行此操作
  • +
    :尝试获取尽可能多的事件(至少1次);如果发现了N个实例,然后需要放弃(其中的一些),则可以从最后一个实例开始执行此操作
  • +?xfooxxxxxxfoo
    ^
    
    xfooxxxxxxfoo
    ^^
    xfooxxxxxxfoo
    ^^^
    [...]
    xfooxxxxxxfoo
    ^^^^^^^^^^^
    xfooxxxxxxfoo
    ^^^^^^^^^^^^
    xfooxxxxxxfoo
    ^^^^^^^^^^^^^
    
    xfooxxxxxxfoo
    ^^^^^^^^^^^^
    
    xfooxxxxxxfoo
    ^^^^^^^^^^^
    xfooxxxxxxfoo
    ^^^^^^^^^^
    
    xfooxxxxxxfoo
    ^^^^^^^^^^^^^
    
    xfooxxxxxxfoo
    ^
    
    xfooxxxxxxfoo
    ^^^^
    
    xfooxxxxxxfoo
    ^
    [...]
    xfooxxxxxxfoo
    ^^^^^^^^^^^^^