贪婪/懒惰(非贪婪)/占有量词如何在内部工作?
How do greedy / lazy (non-greedy) / possessive quantifiers work internally?
我注意到有 3 种不同的 类 量词:贪婪的、惰性的(即非贪婪的)和所有格的。
我知道,粗略地说,greedy 量词尝试通过首先读取整个输入字符串来获得最长的匹配,然后如果尝试保持不变,则一个接一个地截断字符失败; lazy 量词尝试通过首先读取空字符串来获得最短的匹配,如果尝试不断失败,然后一个接一个地添加字符; 占有 量词尝试与贪婪量词相同的方式,但如果第一次尝试失败,它们将停止匹配。
但是,我不确定上述内容具体是如何实施的'internally',并希望得到澄清(希望有示例)。
例如,假设我们的输入字符串为 "fooaaafoooobbbfoo"
。
如果regex是"foo.*"
(贪心),那么regex中的foo
会不会先匹配输入字符串中的foo
,然后.*
读入aaafoooobbbfoo
和 'the entire string' 一样?或者 .*
会先读入 fooaaafoooobbbfoo
作为 'the entire string',然后截断 fooaaafoooobbbfoo
以尝试匹配正则表达式中的 foo
?如果是后者,那么每次尝试fooaaafoooobbbfoo
会从左边截断还是从右边截断?
如果我将 "foo.*"
替换为 ".*foo"
或 "foo.*foo"
作为我的正则表达式,上述问题的答案会改变吗?如果我把那些贪婪的量词改成懒惰的和所有格的呢?
如果正则表达式中有多个量词,引擎将如何处理优先级(如果重要的话)?
提前致谢!
对于你输入的字符串fooaaafoooobbbfoo
.
案例 1: 当您使用此正则表达式时:
foo.*
首先记住引擎从左到右遍历这个事实。
考虑到上面的正则表达式将首先匹配输入开始处的 foo
然后 .*
将贪婪地匹配 longest 可能的匹配是 foo
之后的其余文本,直到结束。此时匹配停止,因为在您的模式中 .*
之后没有任何匹配。
案例 2: 当您使用此正则表达式时:
.*foo
这里再次 .*
将贪婪地匹配 最长 可能的匹配,然后再匹配输入的最后一个 foo
。
案例 3: 当您使用此正则表达式时:
foo.*foo
将首先匹配输入中找到的 foo
,即开始时的 foo
然后 .*
将在匹配之前贪婪地匹配 最长 可能的匹配last foo
即输入的结尾。
案例 4: 当您将此正则表达式与惰性量词一起使用时:
foo.*?foo
将首先匹配输入中找到的 foo
,即开始时的 foo
然后 .*?
将延迟匹配 最短 可能的匹配,然后再匹配next foo
这是 foo
的第二个实例,从输入中的位置 6
开始。
案例 5: 当您将此正则表达式与所有格量词一起使用时:
foo.*+foo
将首先匹配输入中找到的 foo
,即开始时的 foo
然后 .*+
使用 占有量词 ,这意味着 尽可能多次匹配,不回馈。这将贪婪地匹配 longest 可能的匹配直到结束,并且由于所有格量词不允许引擎回溯因此在部分末尾存在 foo
将导致失败,因为引擎将失败匹配最后 foo
.
我注意到有 3 种不同的 类 量词:贪婪的、惰性的(即非贪婪的)和所有格的。
我知道,粗略地说,greedy 量词尝试通过首先读取整个输入字符串来获得最长的匹配,然后如果尝试保持不变,则一个接一个地截断字符失败; lazy 量词尝试通过首先读取空字符串来获得最短的匹配,如果尝试不断失败,然后一个接一个地添加字符; 占有 量词尝试与贪婪量词相同的方式,但如果第一次尝试失败,它们将停止匹配。
但是,我不确定上述内容具体是如何实施的'internally',并希望得到澄清(希望有示例)。
例如,假设我们的输入字符串为 "fooaaafoooobbbfoo"
。
如果regex是"foo.*"
(贪心),那么regex中的foo
会不会先匹配输入字符串中的foo
,然后.*
读入aaafoooobbbfoo
和 'the entire string' 一样?或者 .*
会先读入 fooaaafoooobbbfoo
作为 'the entire string',然后截断 fooaaafoooobbbfoo
以尝试匹配正则表达式中的 foo
?如果是后者,那么每次尝试fooaaafoooobbbfoo
会从左边截断还是从右边截断?
如果我将 "foo.*"
替换为 ".*foo"
或 "foo.*foo"
作为我的正则表达式,上述问题的答案会改变吗?如果我把那些贪婪的量词改成懒惰的和所有格的呢?
如果正则表达式中有多个量词,引擎将如何处理优先级(如果重要的话)?
提前致谢!
对于你输入的字符串fooaaafoooobbbfoo
.
案例 1: 当您使用此正则表达式时:
foo.*
首先记住引擎从左到右遍历这个事实。
考虑到上面的正则表达式将首先匹配输入开始处的 foo
然后 .*
将贪婪地匹配 longest 可能的匹配是 foo
之后的其余文本,直到结束。此时匹配停止,因为在您的模式中 .*
之后没有任何匹配。
案例 2: 当您使用此正则表达式时:
.*foo
这里再次 .*
将贪婪地匹配 最长 可能的匹配,然后再匹配输入的最后一个 foo
。
案例 3: 当您使用此正则表达式时:
foo.*foo
将首先匹配输入中找到的 foo
,即开始时的 foo
然后 .*
将在匹配之前贪婪地匹配 最长 可能的匹配last foo
即输入的结尾。
案例 4: 当您将此正则表达式与惰性量词一起使用时:
foo.*?foo
将首先匹配输入中找到的 foo
,即开始时的 foo
然后 .*?
将延迟匹配 最短 可能的匹配,然后再匹配next foo
这是 foo
的第二个实例,从输入中的位置 6
开始。
案例 5: 当您将此正则表达式与所有格量词一起使用时:
foo.*+foo
将首先匹配输入中找到的 foo
,即开始时的 foo
然后 .*+
使用 占有量词 ,这意味着 尽可能多次匹配,不回馈。这将贪婪地匹配 longest 可能的匹配直到结束,并且由于所有格量词不允许引擎回溯因此在部分末尾存在 foo
将导致失败,因为引擎将失败匹配最后 foo
.