正则表达式入门教程(长文讲解)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观

前言

在编程和文本处理中,正则表达式(Regular Expression,简称 regex 或 regexp)是一种强大的工具,能帮助开发者高效地匹配、查找、替换和验证文本模式。无论是从日志文件中提取关键信息,还是验证用户输入的邮箱格式,正则表达式都能显著提升开发效率。然而,对许多编程初学者而言,正则表达式如同“神秘代码”,其符号和语法令人望而却步。本文将通过 正则表达式入门教程 的形式,以循序渐进的方式拆解其核心概念,并结合实际案例,帮助读者快速掌握这一技能。


基础语法解析:正则表达式如何“阅读”文本?

正则表达式可以看作是“文字版的乐高积木”——通过组合不同的符号和规则,构建出能匹配特定文本模式的“指令”。其基本构成包括普通字符、元字符和量词。

1. 普通字符:直接匹配

普通字符(如字母、数字、空格)在正则表达式中直接表示其本身。例如:

  • 正则表达式 hello 会匹配字符串中的“hello”;
  • 正则表达式 2023 会匹配“2023”这样的年份。

2. 元字符:特殊功能符号

元字符是正则表达式的核心,它们像“开关”一样,改变匹配行为:
| 元字符 | 功能说明 | 示例 |
|--------|----------|------|
| . | 匹配任意单个字符(除换行符外) | a.c 匹配 "abc"、"a2c",但不匹配 "ac" |
| ^ | 匹配字符串开头 | ^start 匹配以 "start" 开头的字符串 |
| $ | 匹配字符串结尾 | end$ 匹配以 "end" 结尾的字符串 |
| | | 表示“或”关系 | cat|dog 匹配 "cat" 或 "dog" |

3. 量词:控制匹配次数

量词定义字符或模式的重复次数,常见的包括:

  • *:匹配前面的元素 零次或多次(如 a* 匹配空字符串、"a"、"aa" 等);
  • +:匹配前面的元素 一次或多次(如 a+ 匹配 "a"、"aa",但不匹配空字符串);
  • ?:匹配前面的元素 零次或一次(如 a? 匹配空字符串或 "a");
  • {n}:精确匹配 n次(如 a{3} 匹配 "aaa");
  • {n,m}:匹配 n到m次(如 a{2,4} 匹配 "aa"、"aaa" 或 "aaaa")。

比喻说明
想象量词是“贪吃的小怪兽”,* 是“能吃光所有食物”,而 ? 是“只吃一口或不吃”。例如:

a.*b  

这条规则会匹配从“a”开始,到“b”结束之间的所有字符(如 "abc"、"a123b")。


元字符进阶:边界、字符集与转义

1. 字符集(Character Set):定义匹配范围

[] 定义一个字符集,匹配其中任意一个字符。例如:

  • [abc] 匹配 "a"、"b" 或 "c";
  • [0-9] 匹配任意数字(等价于 \d)。

否定字符集[^abc] 匹配不在字符集中的字符。

2. 转义特殊字符:用反斜杠 \

若需匹配元字符本身(如匹配 .*),需用 \ 转义。例如:

  • \. 匹配句号;
  • \* 匹配星号。

3. 预定义字符类:简化复杂模式

正则表达式提供预定义字符类,例如:

  • \d:匹配任意数字(等同于 [0-9]);
  • \w:匹配字母、数字或下划线(等同于 [a-zA-Z0-9_]);
  • \s:匹配空白字符(空格、换行、制表符等)。

案例演示
验证一个字符串是否为 4 位纯数字的年份:

^\d{4}$  

这条规则会匹配 "2023",但不会匹配 "202a" 或 "2023a"。


分组与捕获:提取文本片段

1. 捕获组:用 () 围绕模式

分组可以将多个字符视为一个整体,并实现捕获功能。例如:

(cat|dog) is cute  

此规则匹配 "cat is cute" 或 "dog is cute",且捕获“cat”或“dog”作为第一组。

2. 反向引用:引用已捕获的内容

在替换操作中,可通过 \n(n为组号)引用捕获的内容。例如:

const str = 'apple and apple';  
const result = str.replace(/(apple) and \1/, '$1 only');  
// 结果:'apple only'  

此处 \1 引用第一个捕获组(“apple”),实现替换重复内容。

3. 非捕获组:用 (?:...) 忽略捕获

若仅需分组而无需捕获,可用 (?:...)

\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12][0-9]|3[01])  

此规则验证日期格式(如 "2023-09-15"),但不会保存中间的月份和日期。


进阶技巧:边界匹配与贪婪模式

1. 边界匹配:精确控制位置

  • 单词边界 \b:匹配单词的开始或结束位置。例如:

    \bhello\b  
    

    会匹配独立的 "hello",但不会匹配 "hello123" 或 "sayhello"。

  • 非单词边界 \B:与 \b 相反,匹配非单词边界位置。

2. 贪婪与懒惰模式

默认情况下,量词是“贪婪”的,即尽可能匹配最长的字符串。例如:

<a>.*</a>  

在匹配 "text1text2" 时,会匹配到第二个 "",导致范围过长。

懒惰模式通过 *?+? 等修饰符实现最小匹配:

<a>.*?</a>  

此规则会正确匹配第一个 "..." 块。


实战案例:常见场景解析

案例1:验证邮箱格式

邮箱通常包含用户名、@ 符号和域名。正则表达式可设计为:

^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$  

分步解释

  1. ^:匹配字符串开头;
  2. [a-zA-Z0-9._%+-]+:匹配用户名(至少一个字符);
  3. @:匹配 @ 符号;
  4. [a-zA-Z0-9.-]+:匹配域名前缀;
  5. \.[a-zA-Z]{2,}$:匹配顶级域名(如 .com、.org)。

案例2:提取文章中的日期

假设文本中包含日期格式如 "2023-09-15",正则表达式为:

\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])  

此规则通过分组确保:

  • 月份为 01-12;
  • 日期为 01-31(需结合具体月份调整精确性)。

案例3:替换敏感词

若需将文本中的敏感词替换为星号,可使用:

text.replace(/(敏感词1|敏感词2)/g, (match) => '*'.repeat(match.length));  

其中,g 标志表示全局替换。


常见问题与调试技巧

1. 正则表达式不匹配?检查这些点!

  • 是否遗漏转义符?(如匹配 . 需写为 \.);
  • 量词是否过“贪婪”?尝试添加 ? 转为懒惰模式;
  • 是否需要使用全局(g)或多行(m)标志?

2. 在线工具辅助调试

推荐使用 regex101.com 或浏览器开发者工具,输入正则表达式和测试文本,实时查看匹配结果。


结论

正则表达式是一门需要“边学边练”的技能。通过本文的 正则表达式入门教程,我们系统梳理了其核心语法、进阶技巧及实际案例。从基础的字符匹配到复杂的分组捕获,正则表达式能显著提升文本处理的效率。

建议读者从简单场景入手(如验证手机号、提取 URL),逐步挑战复杂需求(如解析 HTML 结构)。同时,善用在线工具和调试技巧,能更快定位问题。掌握正则表达式后,你将解锁编程中更高效、优雅的解决方案。

编程之路永无止境,而正则表达式正是你工具箱中不可或缺的“瑞士军刀”。希望这篇入门教程能为你打开这扇门,未来继续探索更高级的主题(如反向引用、前瞻/后顾断言等),让正则表达式真正成为你的得力伙伴。

最新发布