正则表达式前瞻匹配(零宽度先行断言)

基于 ECMAScript 正则表达式语法

断言不消耗输入中的任何字符,仅判断当前位置是否满足某种条件。例如 ^ 和 $ 分别断言文本的开头和结尾,本身不匹配任何字符。

零宽度正向先行断言

(?=...):当前位置之后的文本能够匹配 ... 时,断言成功。

示例一:(?=(a+))a*b 匹配 baaba

  1. 位置 0(b):a+ 无法匹配,失败。
  2. 位置 1(a):a+ 贪婪匹配 aa(位置 1–2),断言成功,当前位置仍在 1。继续匹配 a*b:a* 贪婪匹配 aa(位置 1–2),b 匹配位置 3 成功。
  3. 最终匹配 aab(位置 1–3),分组 1 捕获 aa。

示例二:(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).{6,} 匹配 abc2ABC

要求包含小写字母、大写字母和数字,且长度至少为 6。依次执行三个前瞻断言(均从位置 0 开始):

(?=.*[a-z]) — 是否包含小写字母

  • .* 贪婪匹配全部 7 字符,[a-z] 无剩余可匹配,失败。
  • 回溯至 6 字符:剩 C,[a-z] 失败。
  • 回溯至 5 字符:剩 B,失败。
  • 回溯至 4 字符:剩 A,失败。
  • 回溯至 3 字符:剩 2,失败。
  • 回溯至 2 字符:剩 c,[a-z] 匹配成功。

(?=.*[A-Z]) — 是否包含大写字母

  • .* 贪婪匹配全部 7 字符,[A-Z] 失败。
  • 回溯至 6 字符:剩 C,[A-Z] 匹配成功。

(?=.*[0-9]) — 是否包含数字

  • .* 贪婪匹配全部 7 字符,[0-9] 失败。
  • 回溯至 6 字符:剩 C,失败。
  • 回溯至 5 字符:剩 B,失败。
  • 回溯至 4 字符:剩 A,失败。
  • 回溯至 3 字符:剩 2,[0-9] 匹配成功。

三个断言均成功,当前位置仍在位置 0。最后 .{6,} 匹配全部 7 个字符,匹配结果为 abc2ABC。

零宽度负向先行断言

(?!...):当前位置之后的文本不能匹配 ... 时,断言成功。

与正向先行断言相反,当 ... 在当前位置匹配失败时,负向断言才算成功。