442. Java 正则表达式 - 量词

文章目录

  • [442. Java 正则表达式 - 量词](#442. Java 正则表达式 - 量词)
    • [1. 量词速查表 📝](#1. 量词速查表 📝)
    • [2. 基本示例 🧪](#2. 基本示例 🧪)
      • [2.1 `?`:零次或一次](#2.1 ?:零次或一次)
      • [2.2 `*`:零次或多次](#2.2 *:零次或多次)
      • [2.3 `+`:一次或多次](#2.3 +:一次或多次)
    • [3. 零长度匹配 Zero-Length Matches ⚠️](#3. 零长度匹配 Zero-Length Matches ⚠️)
    • [4. 限定次数的量词 🎯](#4. 限定次数的量词 🎯)
      • [4.1 恰好 n 次](#4.1 恰好 n 次)
      • [4.2 至少 n 次](#4.2 至少 n 次)
      • [4.3 n 到 m 次](#4.3 n 到 m 次)
    • [5. 贪婪 vs 勉强 vs 独占 🥊](#5. 贪婪 vs 勉强 vs 独占 🥊)
    • [6. 互动练习 🎤](#6. 互动练习 🎤)

442. Java 正则表达式 - 量词

在正则里,量词 的作用就是告诉引擎:

👉 前面的元素要匹配多少次?

比如:

  • a? 表示:零次或一次
  • a* 表示:零次或多次
  • a+ 表示:一次或多次

是不是有点像我们在说话时常用的"至少一次""可以没有""三次刚刚好"?


1. 量词速查表 📝

Greedy (贪婪) Reluctant (勉强) Possessive (独占) 含义
X? X?? X?+ X,出现 0 或 1 次
X* X*? X*+ X,出现 0 次或多次
X+ X+? X++ X,出现 1 次或多次
X{n} X{n}? X{n}+ X,出现 恰好 n 次
X{n,} X{n,}? X{n,}+ X,出现 至少 n 次
X{n,m} X{n,m}? X{n,m}+ X,出现 n 到 m 次之间

⚡ 默认是 贪婪(Greedy)模式

  • 会尽可能多地匹配字符。
  • Reluctant(勉强模式)和 Possessive(独占模式)的区别我们放到最后再深入讲。

2. 基本示例 🧪

2.1 ?:零次或一次

java 复制代码
a?
  • 输入:""(空串) → 匹配成功(因为 0 次也行)
  • 输入:a → 匹配成功
  • 输入:b → 匹配到 空串

👉 ? 最常用于 可选字段

例如:colou?r 可以匹配 colorcolour


2.2 *:零次或多次

java 复制代码
a*
  • 输入:"" → 匹配成功
  • 输入:aaaa → 匹配到 aaaa
  • 输入:b → 匹配到空串

👉 常见场景:匹配任意长度的空格

java 复制代码
\s*

2.3 +:一次或多次

java 复制代码
a+
  • 输入:"" → ❌ 不匹配
  • 输入:a → 匹配成功
  • 输入:aaaa → 匹配到 aaaa

👉 常见场景:手机号(必须是 11 位数字,不允许空)

java 复制代码
\d+

3. 零长度匹配 Zero-Length Matches ⚠️

有些时候,正则匹配的结果是 空字符串。比如:

java 复制代码
a?
  • 输入:a → 匹配到 "a",但在最后索引位置,还会额外匹配一个 ""(空串)。

这就是所谓的 零长度匹配

它可能出现在:

  • 输入串为空时
  • 字符串开头
  • 字符串结尾
  • 两个字符之间

👉 小贴士:

"零长度匹配"很好理解:匹配的是 存在与不存在之间的"空隙"


4. 限定次数的量词 🎯

4.1 恰好 n 次

java 复制代码
a{3}
  • "aa" → ❌ 不匹配
  • "aaa" → ✅ 匹配成功
  • "aaaa" → ✅ 匹配前 3 个

4.2 至少 n 次

java 复制代码
a{3,}
  • "aaa" → ✅
  • "aaaaaa" → ✅
  • "a" → ❌

👉 场景:匹配至少 8 位的密码:

java 复制代码
.{8,}

4.3 n 到 m 次

java 复制代码
a{3,6}
  • "aaaaaa" → 匹配 6 个
  • "aaaaaaaaa" → 匹配 6 个 + 后面的 3 个

👉 场景:手机号(11 位)

java 复制代码
^\d{11}$

👉 邮编(5 到 6 位数字)

java 复制代码
^\d{5,6}$

5. 贪婪 vs 勉强 vs 独占 🥊

假设字符串是 "aaaa",正则是 a+?

  • Greedy 贪婪a+ → 会尽可能多吃 → 匹配 "aaaa"
  • Reluctant 勉强a+? → 会尽可能少吃 → 第一次只匹配 "a",再逐步扩展
  • Possessive 独占a++ → 会"一口吃完" → 匹配 "aaaa",但不会回溯

👉 举例:

java 复制代码
String regex = "a+?b";
String input = "aaab";
  • Greedy:aaa → 再尝试匹配 b ✅
  • Reluctant:a → 再尝试匹配 b,失败 → 再吃一个 → aa,直到匹配到 b
  • Possessive:aaa(独占不回吐) → 再匹配 b ❌

6. 互动练习 🎤

  1. 写一个正则,匹配 3 到 5 位数字的验证码
    👉 提示:^\d{3,5}$
  2. 匹配一段文本里,所有连续出现 2 个以上空格的地方
    👉 提示:\s{2,}
  3. 匹配邮箱前缀,要求 至少 6 位,由字母、数字或下划线组成
    👉 提示:^\w{6,}@