为了更好地理解,让我们应用这三个表达式以及一个捕获组并分析每个行为。
()
捕获组 -括号内的正则表达式必须匹配,并且匹配项将创建捕获组
(?:)
非捕获组 -括号内的正则表达式必须匹配,但不创建捕获组
(?=)
积极向前看 -断言正则表达式必须匹配
(?!)
负面展望 -断言不可能匹配正则表达式
让我们将q(u)i
要退出。q
匹配q并且捕获组u
匹配u。在捕获组中进行匹配并创建捕获组。因此,引擎继续运行i
。并i
会匹配我。最后一次比赛尝试成功。qui被匹配,并且一个捕获组与u创建。
让我们将q(?:u)i
要退出。同样,q
匹配q,非捕获组u
匹配u。从非捕获组进行匹配,但未创建捕获组。因此,引擎继续运行i
。并i
会匹配我。最后一次比赛尝试成功。qui被匹配
让我们将q(?=u)i
要退出。前瞻为正,后跟另一个标记。同样,q
匹配q和u
匹配ü。同样,必须取消前瞻的匹配,因此引擎从i
字符串中退回到u。前瞻成功,因此引擎继续运行i
。但i
不能匹配你。因此,此匹配尝试失败。
让我们将q(?=u)u
要退出。前瞻为正,后跟另一个标记。同样,q
匹配q和u
匹配ü。前瞻的匹配项必须舍弃,因此引擎将从u
字符串中的步骤退回到u。前瞻成功,因此引擎继续运行u
。并且u
会匹配你。因此,此匹配尝试成功。曲匹配
让我们将q(?!i)u
要退出。即使在这种情况下,超前也是正的(因为i
不匹配),并且后面跟随另一个标记。同样,q
匹配q和i
不匹配ü。前瞻的匹配项必须舍弃,因此引擎将从u
字符串中的步骤退回到u。前瞻成功,因此引擎继续运行u
。并且u
会匹配你。因此,此匹配尝试成功。曲匹配
因此,总而言之,前瞻组和非捕获组之间的真正区别在于,如果您只想测试存在性或测试并保存匹配项。捕获组非常昂贵,因此请谨慎使用。