我找到了这本关于正则表达式的出色教程 ,尽管我直观地理解“贪婪”,“勉强”和“可能”量词的做用,但个人理解彷佛还存在严重的漏洞。 正则表达式
具体来讲,在如下示例中: 工具
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”已被检讨 ,等等。 测试
不幸的是,尽管有很好的比喻,我仍是不明白什么是被谁吃掉......你知道另外一个教程,说明(简洁) 如何正则表达式引擎的工做? spa
或者,若是有人能够用不一样的措辞解释下一段,那将不胜感激: code
第一个示例使用贪婪量词。*查找“任何”,零次或屡次,后跟字母“ f”,“ o”,“ o”。 因为量词是贪婪的,所以表达式的。*部分首先会吃掉整个输入字符串。 此时,整个表达式没法成功,由于最后三个字母(“ f”,“ o”,“ o”)已经被消耗( 由谁来使用? )。 所以,匹配器一次( 从右到左? )缓慢退回一个字母,直到最右边的“ foo”出现反响( 这是什么意思? ),这时匹配成功而且搜索结束。 教程
可是,第二个示例是不情愿的,所以它从首先消耗( 由谁来? )“什么都没有”开始。 由于“ foo”没有出如今字符串的开头,因此它被迫吞下( 谁吞了?)第一个字母(“ x”),从而在0和4处触发第一个匹配。咱们的测试工具继续进行直到输入字符串用尽。 它在4和13找到另外一个匹配项。 索引
第三个示例找不到匹配项,由于量词是全部格。 在这种状况下,整个输入字符串将由。* +( 如何使用 )使用,而在表达式末尾不留任何内容来知足“ foo”。 对于但愿在不退缩的状况下抓住全部东西的状况,请使用全部格量词( backful意味着什么? ); 若是没有当即找到匹配项,它将赛过等效的贪婪量词。 字符串
贪婪:“匹配最长的字符序列” get
勉强:“匹配尽量短的字符序列” input
拥有:这有点奇怪,由于它不会(与贪婪和不情愿相反)尝试为整个正则表达式找到匹配项。
顺便说一句:没有任何正则表达式模式匹配器实现将使用回溯。 全部现实生活中的模式匹配器都很是快-几乎与正则表达式的复杂性无关!
这是我使用单元格和索引位置的见解(请参见此处的图,以区分单元格和索引)。
贪婪-尽量匹配贪婪量词和整个正则表达式。 若是没有匹配项,则在贪婪量词上回溯。
输入字符串: 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-经过(单元格十、十一、12-即介于10和13之间的索引)
报告比赛
步骤10:
。*? =''(空白)-经过(尽量少地匹配勉强的量词'。*?'。索引13为空白。)
foo =没有字符能够匹配-失败(索引13以后没有要匹配的字符)
比赛失败。
结果:2场比赛
我发现文本“ xfoo”从索引0开始到索引4结束。
我发现文本“ xxxxxxfoo”从索引4开始到索引13结束。
拥有-尽量匹配全部格量词并匹配整个正则表达式。 不要回溯。
输入字符串: xfooxxxxxxfoo
正则表达式: 。* + foo
上面的正则表达式包含两个部分:“。* +”和“ foo”。
第1步:
。* + = xfooxxxxxxfoo-经过(尽量匹配全部格量词'。*')
foo =没有字符能够匹配-失败(索引13以后没有匹配项)
比赛失败。
注意:不容许回溯。
结果: 0场比赛
贪婪量化涉及在迭代过程当中使用字符串的全部其他未验证字符进行模式匹配。 未经验证的字符从活动序列开始。 每次不进行匹配时,末尾的字符将被隔离,并再次执行检查。
当活动序列仅知足正则表达式模式的前导条件时,将尝试针对隔离区验证其他条件。 若是此验证成功,则隔离区中的匹配字符将获得验证,剩余的不匹配字符将保持未验证状态,并将在下一次迭代中从新开始该过程时使用。
字符流是从活动序列进入隔离区的。 结果是,匹配中包含了尽量多的原始序列。
勉强量化与贪婪限定基本相同,不一样之处在于字符流是相反的,也就是说,它们从隔离区开始并流入活动序列 。 结果是,匹配中包含的原始序列越少越好。
全部权量化没有隔离区 ,包括固定激活序列中的全部内容 。
这只是个人练习输出,能够将场景可视化-
我会试一试。
贪婪的量词首先会尽量匹配。 所以.*
匹配整个字符串。 而后,匹配器尝试匹配如下的f
,但没有剩余字符。 所以它“回溯了”,使贪婪的量词少匹配一件事(使字符串末尾的“ o”不匹配)。 那仍然与正则表达式中的f
不匹配,所以它又“回溯”了一步,使贪婪的量词再次匹配少了一点(使字符串末尾的“ oo”不匹配)。 它仍然与正则表达式中的f
不匹配,所以它又回退了一步(使字符串末尾的“ foo”不匹配)。 如今,匹配器最终匹配正则表达式中的f
,而且o
和下一个o
也被匹配。 成功!
勉强或“非贪婪”的量词首先匹配得尽量少。 所以, .*
首先不匹配任何内容,从而使整个字符串不匹配。 而后,匹配器尝试匹配后跟的f
,可是字符串的不匹配部分以“ x”开头,所以不起做用。 所以,匹配器回溯,使非贪婪量词又匹配一件事(如今匹配“ x”,而使“ fooxxxxxxfoo”不匹配)。 而后,它尝试匹配成功的f
,而且正则表达式中的o
和下一个o
也匹配。 成功!
在您的示例中,而后按照相同的过程,以字符串的剩余不匹配部分从新开始该过程。
全部格量词就像贪婪的量词同样,可是不会回溯。 所以,它以.*
开头,匹配整个字符串,不留任何不匹配的内容。 这样就没有其余要与正则表达式中的f
匹配的东西了。 因为全部格量词不会回溯,所以匹配失败。