正则表达式从入门到精通
正则表达式从入门到精通教程
这个教程会通过三个阶段(入门、进阶、精通)带你逐步学习正则表达式,附带实战练习和如何逐步编写符合需求的正则表达式。
阶段 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
- 步骤:
- 分析结构:由数字、短横线组成,格式是
三位数字-三位数字-四位数字
。 - 转换为正则:
\d{3}-\d{3}-\d{4}
。
- 分析结构:由数字、短横线组成,格式是
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+$
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
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})
- 格式是
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>
。
pattern = r"<.*?>"
text = "<div>Hello</div><div>World</div>"
matches = re.findall(pattern, text)
print("匹配结果:", matches)
2. 高级应用:嵌套匹配
任务:匹配嵌套结构(如数学表达式)
正则表达式不能直接处理嵌套结构,但可以通过多步操作实现。
- 示例文本:
(a + (b - c))
- 分析需求:
- 提取匹配外层和内层括号。
- 转换为正则:
\([^()]*\)
pattern = r"\([^()]*\)"
text = "(a + (b - c)) + (d / e)"
matches = re.findall(pattern, text)
print("匹配括号内容:", matches)
3. 动态构造正则表达式
使用 re.compile
动态创建正则表达式,支持多种标志。
import re
flags = re.IGNORECASE | re.MULTILINE
pattern = re.compile(r"hello", flags)
text = "Hello world\nhello again"
matches = pattern.findall(text)
print("匹配结果:", matches)
总结:如何编写正则表达式?
- 分析目标结构:
- 定位模式中的固定部分和可变部分。
- 确定字符类型(数字、字母、特殊字符)。
- 逐步分解编写:
- 从简单匹配入手,逐步增加复杂逻辑。
- 测试表达式:
- 使用在线工具(如 Regex101)。
- 优化与调试:
- 使用非贪婪模式或分组引用优化结果。
附:正则表达式一览表
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] | 匹配 a 到 z 的任意小写字母 |
预定义字符集:
表达式 | 作用 | 示例 | 匹配结果 |
---|---|---|---|
\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 |
原文地址:https://blog.csdn.net/cgy091107/article/details/143836996
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!