0Pricing
Java Academy · 课时

使用 Pattern 和 Matcher 处理正则表达式

使用 Java 正则表达式验证电子邮件、提取子字符串和替换匹配模式

使用 Pattern 和 Matcher 处理正则表达式 是 CoddyKit 上的免费 Java Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。

使用 Pattern 和 Matcher 处理正则表达式

Java 的 java.util.regex 包提供了 Pattern 和 Matcher,可用于强大的文本匹配、验证、提取和替换。

为什么使用正则表达式

正则表达式(regex)是用于匹配文本的模式。在 Java 中,它们可用于验证电子邮件地址和电话号码、从日志中提取数据,以及解析结构化文本。

import java.util.regex.*;

// Is this a valid email?
String email = "alice@example.com";
boolean valid = email.matches("[a-zA-Z0-9._%+\\-]+@[a-zA-Z0-9.\\-]+\\.[a-zA-Z]{2,}");
System.out.println(valid); // true

// Extract version numbers from a string
String log = "App v1.2.3 deployed; api v2.0.0 started";
Pattern p = Pattern.compile("v(\\d+\\.\\d+\\.\\d+)");
Matcher m = p.matcher(log);
while (m.find()) System.out.println(m.group(1));
// 1.2.3 
// 2.0.0

正则表达式语法基础

主要的正则表达式元字符:

  • . — 任意字符
  • \d — 数字;\w — 单词字符;\s — 空白字符
  • * — 0 次或更多;+ — 1 次或更多;? — 0 次或 1 次
  • {n,m} — 重复 n 到 m 次
  • ^/$ — 行首/行尾
  • [abc] — 字符类
// In Java strings, backslash must be doubled: \d = "\\d"
Pattern digit   = Pattern.compile("\\d+");      // one or more digits
Pattern word    = Pattern.compile("\\w{3,20}");  // 3-20 word chars
Pattern space   = Pattern.compile("\\s+");       // whitespace
Pattern phone   = Pattern.compile("\\d{3}-\\d{3}-\\d{4}"); // 555-867-5309

System.out.println(digit.matcher("42").matches());       // true
System.out.println(phone.matcher("555-867-5309").matches()); // true

Pattern.compile 与 Matcher

请编译一次模式,然后使用 Matcher 处理多个输入;与反复使用 String.matches() 进行验证相比,这样更加高效。

import java.util.regex.*;

Pattern emailPattern = Pattern.compile(
    "^[a-zA-Z0-9._%+\\-]+@[a-zA-Z0-9.\\-]+\\.[a-zA-Z]{2,6}$"
);

String[] emails = {"alice@example.com", "bad@", "test.user@co.uk", "no-at-sign"};
for (String e : emails) {
    Matcher m = emailPattern.matcher(e);
    System.out.println(e + " -> " + (m.matches() ? "valid" : "invalid"));
}

find() 与 matches()

matches() 会检查整个字符串。find() 会在字符串中查找下一个匹配项。搜索时请使用 find,进行完整验证时请使用 matches。

import java.util.regex.*;

Pattern price = Pattern.compile("\\d+\\.\\d{2}");

String invoice = "Total: 129.99, Tax: 10.40, Shipping: 5.00";
Matcher m = invoice.matcher(invoice);

// find() locates all matches
while (m.find()) {
    System.out.println("Found: " + m.group() + " at " + m.start());
}
// Found: 129.99 at 7
// Found: 10.40 at 20
// Found: 5.00 at 34

捕获组

圆括号可以创建捕获组。请使用 group(n) 提取匹配到的子字符串。

import java.util.regex.*;

Pattern date = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
Matcher m = date.matcher("Deployed on 2024-06-15 and 2024-07-01");

while (m.find()) {
    String year  = m.group(1);
    String month = m.group(2);
    String day   = m.group(3);
    System.out.println(year + "/" + month + "/" + day);
}
// 2024/06/15
// 2024/07/01

命名组

命名组 (?<name>...) 可以让捕获组更易读,并且可以通过名称访问。

import java.util.regex.*;

Pattern log = Pattern.compile(
    "(?<timestamp>\\d{4}-\\d{2}-\\d{2}) (?<level>[A-Z]+) (?<message>.+)"
);

String line = "2024-06-15 ERROR Database connection failed";
Matcher m = log.matcher(line);

if (m.matches()) {
    System.out.println("Time: "    + m.group("timestamp"));
    System.out.println("Level: "   + m.group("level"));
    System.out.println("Message: " + m.group("message"));
}
// Time: 2024-06-15
// Level: ERROR
// Message: Database connection failed

replaceAll 与 replaceFirst

基于模式进行替换:替换所有出现的内容,或只替换第一个匹配项。

import java.util.regex.*;

String text = "Call us at 123-456-7890 or 098-765-4321";

// Mask phone numbers for privacy logs
String masked = text.replaceAll("\\d{3}-\\d{3}-\\d{4}", "XXX-XXX-XXXX");
System.out.println(masked);
// Call us at XXX-XXX-XXXX or XXX-XXX-XXXX

// Replace multiple whitespace with single space
String cleaned = "too   many   spaces".replaceAll("\\s+", " ");
System.out.println(cleaned); // too many spaces

使用正则表达式调用 split()

String.split() 接受正则表达式。您可以使用它根据多个分隔符或复杂的分隔模式进行拆分。

// Split on comma with optional spaces
String csv = "Alice, Bob,  Charlie,Diana";
String[] names = csv.split("\\s*,\\s*");
for (String name : names) System.out.println("'" + name + "'");
// 'Alice' 'Bob' 'Charlie' 'Diana'

// Split on any whitespace
String words = "one  two\tthree  four";
String[] parts = words.split("\\s+");
System.out.println(parts.length); // 4

// Limit splits
String line = "key=value=extra";
String[] kv = line.split("=", 2); // [key, value=extra]

Pattern 标志

标志可以修改正则表达式的行为:不区分大小写、MULTILINE、DOTALL。

import java.util.regex.*;

// Case-insensitive match
Pattern p = Pattern.compile("hello", Pattern.CASE_INSENSITIVE);
System.out.println(p.matcher("HELLO World").find()); // true

// MULTILINE: ^ and $ match line boundaries
Pattern multi = Pattern.compile("^ERROR", Pattern.MULTILINE);
String logs = "INFO start\nERROR crash\nINFO end";
Matcher m = multi.matcher(logs);
int count = 0;
while (m.find()) count++;
System.out.println("ERROR lines: " + count); // 1

实践:日志解析器

使用命名组解析 Apache 风格的访问日志行。

import java.util.regex.*;

Pattern accessLog = Pattern.compile(
    "(?<ip>[\\d.]+) - - \\[(?<time>[^\\]]+)\\] " +
    "\"(?<method>[A-Z]+) (?<path>[^ ]+)[^\"]*\" " +
    "(?<status>\\d{3}) (?<bytes>\\d+)"
);

String line = "192.168.1.1 - - [27/May/2024:10:30:00 +0000] \"GET /api/products HTTP/1.1\" 200 1024";
Matcher m = accessLog.matcher(line);
if (m.matches()) {
    System.out.println("IP: "     + m.group("ip"));
    System.out.println("Method: " + m.group("method"));
    System.out.println("Status: " + m.group("status"));
}

快速检查

Matcher 中的 matches() 与 find() 有什么区别?

回顾:使用 Pattern 和 Matcher 处理正则表达式

要点:

  • Pattern.compile() 会编译正则表达式;Matcher 会针对字符串进行测试
  • matches() 会验证整个字符串;find() 会搜索匹配项
  • 捕获组 () 可以提取子字符串;请通过 group(n) 或 group("name") 访问它们
  • 命名组 (?<name>...) 可以让模式更易读
  • replaceAll() 和 split() 接受正则表达式模式,可灵活处理文本
  • 请使用 Pattern.CASE_INSENSITIVE、MULTILINE、DOTALL 标志来修改匹配行为

常见问题解答

「使用 Pattern 和 Matcher 处理正则表达式」课时是免费的吗?

是的 — 「使用 Pattern 和 Matcher 处理正则表达式」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。

「使用 Pattern 和 Matcher 处理正则表达式」这节课中我会学到什么?

使用 Java 正则表达式验证电子邮件、提取子字符串和替换匹配模式 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Java Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「使用 Pattern 和 Matcher 处理正则表达式」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Java Academy 课中编写并运行代码吗?

能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. String 不可变性与字符串池
  2. 使用 StringBuilder 高效拼接
  3. 文本块与 String.format
  4. 使用 Pattern 和 Matcher 处理正则表达式
← 返回 Java Academy