正则表达式从入门到精通

正则表达式从入门到精通教程

这个教程会通过三个阶段(入门、进阶、精通)带你逐步学习正则表达式,附带实战练习和如何逐步编写符合需求的正则表达式。


阶段 1:入门

1. 什么是正则表达式?

正则表达式(Regular Expression, regex)是一种用于字符串匹配和处理的模式描述语言,可以用来搜索、替换和验证字符串。


2. 必备基础概念

特殊符号
  • . : 匹配任意单个字符(除换行符)。
    • 示例:a.c 匹配 abc, a1c 等。
  • [] : 匹配字符集中的任意一个字符。
    • 示例:[abc] 匹配 a, b, c
  • - : 表示字符范围。
    • 示例:[a-z] 匹配所有小写字母。
  • \ : 转义符,用于匹配特殊字符本身。
    • 示例:\. 匹配点号 .
量词
  • * : 匹配前面的内容 0 次或多次。
    • 示例:a* 匹配 "", a, aaa
  • + : 匹配前面的内容 1 次或多次。
    • 示例:a+ 匹配 a, aa
  • ? : 匹配前面的内容 0 次或 1 次。
    • 示例:a? 匹配 "", a
  • {n} : 匹配前面的内容正好 n 次。
    • 示例:a{3} 匹配 aaa

3. 入门实战:用正则匹配简单的格式

任务:匹配一个简单的电话号码格式
  • 示例号码:123-456-7890
  • 步骤:
    1. 分析结构:由数字、短横线组成,格式是 三位数字-三位数字-四位数字
    2. 转换为正则:\d{3}-\d{3}-\d{4}
python 复制代码
import re

pattern = r"\d{3}-\d{3}-\d{4}"
text = "我的电话是 123-456-7890,请联系我。"
match = re.search(pattern, text)
if match:
    print("找到电话号码:", match.group())

阶段 2:进阶

1. 边界匹配

  • ^ : 匹配字符串的开头。
    • 示例:^hello 匹配以 hello 开头的字符串。
  • $ : 匹配字符串的结尾。
    • 示例:world$ 匹配以 world 结尾的字符串。
任务:验证字符串是否是邮箱格式
  • 示例邮箱:example@mail.com
  • 分析结构:
    • 开头是字母或数字,可能包含下划线、点号。
    • 接着是 @,后面是域名。
    • 域名部分由字母数字组成,最后是点加后缀。
  • 转换为正则:^\w+@\w+\.\w+$
python 复制代码
pattern = r"^\w+@\w+\.\w+$"
email = "example@mail.com"
if re.match(pattern, email):
    print("合法邮箱")
else:
    print("非法邮箱")

2. 分组与引用

分组用 () 表示,引用用 \数字 指代之前的分组。

任务:匹配重复的单词
  • 示例文本:hello hello world
  • 分析需求:
    • 匹配相邻两个完全相同的单词。
    • 转换为正则:\b(\w+)\s+\1\b
python 复制代码
pattern = r"\b(\w+)\s+\1\b"
text = "hello hello world"
match = re.search(pattern, text)
if match:
    print("找到重复单词:", match.group())

3. 实战练习:提取日期

  • 示例日期:2024-11-17
  • 分析需求:
    • 格式是 年-月-日
    • 年是四位数字,月和日是两位数字。
    • 转换为正则:(\d{4})-(\d{2})-(\d{2})
python 复制代码
pattern = r"(\d{4})-(\d{2})-(\d{2})"
date = "今天是 2024-11-17。"
match = re.search(pattern, date)
if match:
    year, month, day = match.groups()
    print(f"提取日期: 年={year}, 月={month}, 日={day}")

阶段 3:精通

1. 贪婪与懒惰模式

  • 默认是贪婪模式:尽可能多地匹配。
  • ? 转为懒惰模式:尽可能少地匹配。
任务:匹配 HTML 标签内容
  • 示例文本:<div>Hello</div><div>World</div>
  • 贪婪模式:<.*> 会匹配整个 <div>Hello</div><div>World</div>
  • 懒惰模式:<.*?> 会分别匹配 <div></div>
python 复制代码
pattern = r"<.*?>"
text = "<div>Hello</div><div>World</div>"
matches = re.findall(pattern, text)
print("匹配结果:", matches)

2. 高级应用:嵌套匹配

任务:匹配嵌套结构(如数学表达式)

正则表达式不能直接处理嵌套结构,但可以通过多步操作实现。

  • 示例文本:(a + (b - c))
  • 分析需求:
    • 提取匹配外层和内层括号。
  • 转换为正则:\([^()]*\)
python 复制代码
pattern = r"\([^()]*\)"
text = "(a + (b - c)) + (d / e)"
matches = re.findall(pattern, text)
print("匹配括号内容:", matches)

3. 动态构造正则表达式

使用 re.compile 动态创建正则表达式,支持多种标志。

python 复制代码
import re

flags = re.IGNORECASE | re.MULTILINE
pattern = re.compile(r"hello", flags)
text = "Hello world\nhello again"
matches = pattern.findall(text)
print("匹配结果:", matches)

总结:如何编写正则表达式?

  1. 分析目标结构:
  • 定位模式中的固定部分和可变部分。
  • 确定字符类型(数字、字母、特殊字符)。
  1. 逐步分解编写:
  • 从简单匹配入手,逐步增加复杂逻辑。
  1. 测试表达式:
  • 使用在线工具(如 Regex101)。
  1. 优化与调试:
  • 使用非贪婪模式或分组引用优化结果。

附:正则表达式一览表

1. 元字符(Metacharacters)

元字符是正则表达式的核心,用于匹配特定类型的字符或定义模式。

基本元字符:

元字符 作用 示例 匹配结果
. 匹配任意单个字符(除了换行符) a.c 匹配 abc, a1c
\ 转义符,用于匹配特殊字符本身 a\.c 匹配 a.c
^ 匹配字符串的开头 ^abc 匹配以 abc 开头的字符串
$ 匹配字符串的结尾 xyz$ 匹配以 xyz 结尾的字符串
* 匹配前一个字符 0 次或多次 a* 匹配 "", a, aaa
+ 匹配前一个字符 1 次或多次 a+ 匹配 a, aa 等,但不匹配 ""
? 匹配前一个字符 0 次或 1 次 a? 匹配 "", a
{n} 匹配前一个字符正好 n 次 a{3} 匹配 aaa
{n,} 匹配前一个字符至少 n 次 a{2,} 匹配 aa, aaa
{n,m} 匹配前一个字符至少 n 次,至多 m 次 a{2,4} 匹配 aa, aaa, aaaa

字符集和范围:

元字符 作用 示例 匹配结果
[] 匹配括号内任意字符 [abc] 匹配 a, b, c
[^] 匹配不在括号内的字符 [^abc] 匹配除 a, b, c 以外的字符
- 指定字符范围 [a-z] 匹配 az 的任意小写字母

预定义字符集:

表达式 作用 示例 匹配结果
\d 匹配任意数字(0-9) \d+ 匹配 123, 4
\D 匹配任意非数字 \D+ 匹配 abc, !@#
\w 匹配任意单词字符(字母、数字或下划线) \w+ 匹配 abc, a1_
\W 匹配任意非单词字符 \W+ 匹配 @#$
\s 匹配任意空白字符(空格、制表符等) \s+ 匹配空格、换行符等
\S 匹配任意非空白字符 \S+ 匹配 abc, 123

2. 匹配模式(Greedy vs Lazy)

正则表达式默认是贪婪模式(尽可能多地匹配),但可以通过 ? 使其变为非贪婪模式(尽可能少地匹配)。

表达式 作用 示例 匹配结果
.* 贪婪:匹配尽可能多的字符 <.*> 匹配整个 <html><body>
.*? 非贪婪:匹配尽可能少的字符 <.*?> 分别匹配 <html><body>

3. 分组与引用

表达式 作用 示例 匹配结果
() 定义一个组 (abc)+ 匹配 abc, abcabc
(?:...) 非捕获组,不保存匹配结果 (?:abc)+ 匹配但不保存组
\n 引用第 n 个捕获组 (a)(b)\1\2 匹配 abab

4. 边界匹配

表达式 作用 示例 匹配结果
\b 匹配单词边界 \bword\b 匹配 word ,但不匹配 sword
\B 匹配非单词边界 \Bword\B 匹配 sworded 中的 word

5. 标志(Flags)

标志修改正则表达式的行为:

标志 作用 示例
re.IGNORECASE / re.I 忽略大小写 re.match("abc", "ABC", re.I)
re.DOTALL / re.S . 匹配换行符 re.match("a.b", "a\nb", re.S)
re.MULTILINE / re.M 多行模式,^$ 匹配每一行 re.match("^abc$", "abc\ndef", re.M)

6. 常见正则表达式例子

表达式 匹配内容
^\d{4}-\d{2}-\d{2}$ 日期格式:YYYY-MM-DD
\w+@\w+\.\w+ 电子邮件地址
https?://\S+ 匹配 URL
\d{3}-\d{3}-\d{4} 电话号码:123-456-7890
相关推荐
羊小猪~~2 小时前
前端入门一之ES6--递归、浅拷贝与深拷贝、正则表达式、es6、解构赋值、箭头函数、剩余参数、String、Set
开发语言·前端·javascript·css·正则表达式·html·es6
gorgor在码农6 小时前
正则表达式完全指南,总结全面通俗易懂
正则表达式
生椰拿铁You15 小时前
正则表达式(补充)
正则表达式
PythonFun1 天前
Excel365和WPS中提取字符串的五种方法
正则表达式·excel·wps
石牌桥网管1 天前
用正则表达式检查是IP否为内网地址
java·c++·golang·正则表达式·php·c
chusheng18401 天前
Python 正则表达式进阶用法:字符集与字符范围详解
java·python·正则表达式
我爱学习_zwj3 天前
ArkTS的进阶语法-4(函数补充,正则表达式)
前端·华为·正则表达式·harmonyos
平头哥在等你3 天前
Python中的正则表达式教程
python·正则表达式
宋发元4 天前
如何使用正则表达式验证域名
python·mysql·正则表达式