贪婪vs.勉强vs.占有量词

孤街浪徒 提交于 2020-03-03 22:02:55

我找到了这本关于正则表达式的出色教程 ,尽管我直观地理解“贪婪”,“勉强”和“可能”量词的作用,但我的理解似乎还存在严重的漏洞。

具体来说,在以下示例中:

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.

解释提到了吃掉整个输入字符串,字母被消耗 ,匹配器退回 ,最右端出现的“ foo”已被反省 ,等等。

不幸的是,尽管有很好的比喻,我还是不明白什么是被谁吃掉......你知道另一个教程,说明(简洁) 如何正则表达式引擎的工作?

或者,如果有人可以用不同的措辞解释下一段,那将不胜感激:

第一个示例使用贪婪量词。*查找“任何”,零次或多次,后跟字母“ f”,“ o”,“ o”。 由于量词是贪婪的,因此表达式的。*部分首先会吃掉整个输入字符串。 此时,整个表达式无法成功,因为最后三个字母(“ f”,“ o”,“ o”)已经被消耗( 由谁来使用? )。 因此,匹配器一次( 从右到左? )缓慢退回一个字母,直到最右边的“ foo”出现反响( 这是什么意思? ),这时匹配成功并且搜索结束。

但是,第二个示例是不情愿的,因此它从首先消耗( 由谁来? )“什么都没有”开始。 因为“ foo”没有出现在字符串的开头,所以它被迫吞下( 吞了?)第一个字母(“ x”),从而在0和4处触发第一个匹配。我们的测试工具继续进行直到输入字符串用尽。 它在4和13找到另一个匹配项。

第三个示例找不到匹配项,因为量词是所有格。 在这种情况下,整个输入字符串将由。* +( 如何使用 )使用,而在表达式末尾不留任何内容来满足“ foo”。 对于希望在不退缩的情况下抓住所有东西的情况,请使用所有格量词( backful意味着什么? ); 如果没有立即找到匹配项,它将胜过等效的贪婪量词。


#1楼

贪婪:“匹配最长的字符序列”

勉强:“匹配尽可能短的字符序列”

拥有:这有点奇怪,因为它不会(与贪婪和不情愿相反)尝试为整个正则表达式找到匹配项。

顺便说一句:没有任何正则表达式模式匹配器实现将使用回溯。 所有现实生活中的模式匹配器都非常快-几乎与正则表达式的复杂性无关!


#2楼

这是我使用单元格和索引位置的看法(请参见此处图,以区分单元格和索引)。

贪婪-尽可能匹配贪婪量词和整个正则表达式。 如果没有匹配项,则在贪婪量词上回溯。

输入字符串: xfooxxxxxxfoo
正则表达式: 。* foo

上面的正则表达式包含两个部分:
(我和
(ii)'foo'

下面的每个步骤将分析这两个部分。 大括号内说明了与“通过”或“失败”匹配的其他注释。

第1步:
(i)。* = xfooxxxxxxfoo-通过('。*'是一个贪婪的量词,将使用整个输入字符串)
(ii)foo =索引13之后没有字符可匹配-失败
比赛失败。

第2步:
(i)。* = xfooxxxxxxfo-通过(贪婪量词'。*'的回溯)
(ii)foo = o-失败
比赛失败。

第三步:
(i)。* = xfooxxxxxxf-通过(贪婪量词“。*”的回溯)
(ii)foo = oo-失败
比赛失败。

第四步:
(i)。* = xfooxxxxxx-通过(贪婪量词“。*”的回溯)
(ii)foo = foo-通过
报告比赛

结果:1场比赛
我发现文本“ xfooxxxxxxfoo”从索引0开始到索引13结束。

勉强的-尽可能少地匹配勉强的量词,并匹配整个正则表达式。 如果不匹配,则将字符添加到勉强的量词中。

输入字符串: xfooxxxxxxfoo
正则表达式: 。*?foo

上面的正则表达式包含两个部分:
(一世) '。*?' 和
(ii)'foo'

第1步:
。*? =''(空白)-通过(与尽可能少的量词'。*?'匹配。具有''的索引0是匹配项。)
foo = xfo-失败(单元格0,1,2-即索引介于0和3之间)
比赛失败。

第2步:
。*? = x-通过(将字符添加到勉强的量词“。*?”。具有“ x”的单元格0是匹配项。)
foo = foo-通过
报告比赛

第三步:
。*? =''(空白)-通过(与尽可能少的勉强量词'。*?'匹配。具有''的索引4是匹配项。)
foo = xxx-失败(单元格4,5,6-即索引介于4到7之间)
比赛失败。

第四步:
。*? = x-通过(将字符添加到不希望的量词“。*?”。单元格4。)
foo = xxx-失败(单元格5,6,7-即索引介于5到8之间)
比赛失败。

步骤5:
。*? = xx-通过(将字符添加到勉强的量词'。*?'。单元格4到5。)
foo = xxx-失败(单元格6,7,8-即索引在6到9之间)
比赛失败。

步骤6:
。*? = xxx-通过(将字符添加到勉强的量词'。*?'。单元格4到6。)
foo = xxx-失败(单元格7,8,9-即索引介于7到10之间)
比赛失败。

步骤7:
。*? = xxxx-通过(将字符添加到勉强的量词“。*?”。单元格4至7。)
foo = xxf-失败(单元格8,9,10-即8到11之间的索引)
比赛失败。

步骤8:
。*? = xxxxx-通过(将字符添加到勉强的量词'。*?'。单元格4到8。)
foo = xfo-失败(单元格9,10,11-即9到12之间的索引)
比赛失败。

步骤9:
。*? = xxxxxx-通过(将字符添加到勉强的量词'。*?'。单元格4到9。)
foo = foo-通过(单元格10、11、12-即介于10和13之间的索引)
报告比赛

步骤10:
。*? =''(空白)-通过(尽可能少地匹配勉强的量词'。*?'。索引13为空白。)
foo =没有字符可以匹配-失败(索引13之后没有要匹配的字符)
比赛失败。

结果:2场比赛
我发现文本“ xfoo”从索引0开始到索引4结束。
我发现文本“ xxxxxxfoo”从索引4开始到索引13结束。

拥有-尽可能匹配所有格量词并匹配整个正则表达式。 不要回溯。

输入字符串: xfooxxxxxxfoo
正则表达式: 。* + foo

上面的正则表达式包含两个部分:“。* +”和“ foo”。

第1步:
。* + = xfooxxxxxxfoo-通过(尽可能匹配所有格量词'。*')
foo =没有字符可以匹配-失败(索引13之后没有匹配项)
比赛失败。

注意:不允许回溯。

结果: 0场比赛


#3楼

贪婪量化涉及在迭代过程中使用字符串的所有其余未验证字符进行模式匹配。 未经验证的字符从活动序列开始。 每次不进行匹配时,末尾的字符将被隔离,并再次执行检查。

当活动序列仅满足正则表达式模式的前导条件时,将尝试针对隔离区验证其余条件。 如果此验证成功,则隔离区中的匹配字符将得到验证,剩余的不匹配字符将保持未验证状态,并将在下一次迭代中重新开始该过程时使用。

字符流是从活动序列进入隔离区的。 结果是,匹配中包含了尽可能多的原始序列。

勉强量化与贪婪限定基本相同,不同之处在于字符流是相反的,也就是说,它们从隔离区开始并流入活动序列 。 结果是,匹配中包含的原始序列越少越好。

所有权量化没有隔离区 ,包括固定激活序列中的所有内容


#4楼

这只是我的练习输出,可以将场景可视化-


#5楼

我会试一试。

贪婪的量词首先会尽可能匹配。 因此.*匹配整个字符串。 然后,匹配器尝试匹配以下的f ,但没有剩余字符。 因此它“回溯了”,使贪婪的量词少匹配一件事(使字符串末尾的“ o”不匹配)。 那仍然与正则表达式中的f不匹配,因此它又“回溯”了一步,使贪婪的量词再次匹配少了一点(使字符串末尾的“ oo”不匹配)。 它仍然与正则表达式中的f不匹配,因此它又回退了一步(使字符串末尾的“ foo”不匹配)。 现在,匹配器最终匹配正则表达式中的f ,并且o和下一个o也被匹配。 成功!

勉强或“非贪婪”的量词首先匹配得尽可能少。 因此, .*首先不匹配任何内容,从而使整个字符串不匹配。 然后,匹配器尝试匹配后跟的f ,但是字符串的不匹配部分以“ x”开头,因此不起作用。 因此,匹配器回溯,使非贪婪量词又匹配一件事(现在匹配“ x”,而使“ fooxxxxxxfoo”不匹配)。 然后,它尝试匹配成功的f ,并且正则表达式中的o和下一个o也匹配。 成功!

在您的示例中,然后按照相同的过程,以字符串的剩余不匹配部分重新开始该过程。

所有格量词就像贪婪的量词一样,但是不会回溯。 因此,它以.*开头,匹配整个字符串,不留任何不匹配的内容。 这样就没有其他要与正则表达式中的f匹配的东西了。 由于所有格量词不会回溯,因此匹配失败。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!