我最近不得不向其他人解释原子组,我想我会在这里调整并分享这个例子。
考虑 /the (big|small|biggest) (cat|dog|bird)/
粗体匹配
演示
对于第一行,正则表达式引擎会找到the . 然后它会继续处理我们的形容词(big, small, biggest),它会发现big。匹配big后,它继续并找到空间。然后它会查看我们的宠物(cat, dog, bird),找到cat,跳过它,然后找到dog。
对于第二行,我们的正则表达式会找到the . 它会继续查看big,跳过它,查看并查找small。它找到空格,跳过cat并且dog因为它们不匹配,然后找到bird.
对于第三行,我们的正则表达式会 find the ,它会继续查找与当前要求big匹配的内容,然后继续。它找不到空间,所以它回溯(将位置倒回到它所做的最后选择)。它会跳过、跳过并查找也符合即时要求的内容。然后它找到空间。它跳过并匹配。bigsmallbiggestcatdog
对于第四行,我们的正则表达式会找到the . 它会继续查看big,跳过它,查看并查找small。然后它找到空间。它查看并匹配cat.
考虑 /the (?>big|small|biggest) (cat|dog|bird)/
注意?>形容词的原子组。
粗体匹配
演示
对于第一行、第二行和第四行,我们将得到相同的结果。
对于第三行,我们的正则表达式会 find the ,它会继续查找与当前要求big匹配的,然后继续。它找不到空间,但作为引擎做出的最后选择的原子组不允许重新检查该选择(禁止回溯)。由于它不能做出新的选择,所以匹配必须失败,因为我们的简单表达式没有其他选择。
这只是一个基本的总结。引擎不需要查看整个cat就知道它不匹配dog,只需查看c就足够了。在尝试匹配bird 时,cincat和din 狗足以告诉引擎检查其他选项。
但是,如果您有 ... ((cat|snake)|dog|bird),那么引擎当然还需要检查蛇,然后再掉到前一组并检查狗和鸟。
还有很多选择是引擎在不经过可能看起来不匹配的情况下无法决定的,这就是导致回溯的原因。如果有((red)?cat|dog|bird),引擎将查看r,退出,注意?量词,忽略子组(red),并寻找匹配项。