为了更好地理解,让我们应用这三个表达式以及一个捕获组并分析每个行为。
() 捕获组 -括号内的正则表达式必须匹配,并且匹配项将创建捕获组
(?:) 非捕获组 -括号内的正则表达式必须匹配,但不创建捕获组
(?=) 积极向前看 -断言正则表达式必须匹配
(?!) 负面展望 -断言不可能匹配正则表达式
让我们将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会匹配你。因此,此匹配尝试成功。曲匹配
因此,总而言之,前瞻组和非捕获组之间的真正区别在于,如果您只想测试存在性或测试并保存匹配项。捕获组非常昂贵,因此请谨慎使用。