正则表达式(Regular Expression, Regex)详解
正则表达式是一种用来匹配字符串的模式,它为文本处理提供了强大的功能,可以用于查找、替换、提取特定模式的文本。正则表达式广泛应用于文本搜索、数据验证、文本替换等场景。
一、正则表达式的基本语法
正则表达式由字符、元字符和量词组成。通过它们的组合,可以构建出非常复杂的匹配规则。
1. 元字符(Metacharacters)
元字符是正则表达式中的特殊字符,用于定义某种特定的匹配模式:
元字符 | 含义 |
---|---|
. | 匹配任意单个字符(除换行符) |
^ | 匹配字符串的开头 |
$ | 匹配字符串的结尾 |
* | 匹配前面的字符零次或多次 |
+ | 匹配前面的字符一次或多次 |
? | 匹配前面的字符零次或一次 |
[] | 匹配括号内的任意字符(字符集) |
` | ` |
() | 分组,括号内的内容作为一个整体匹配 |
\ | 转义符,表示将元字符转换为普通字符 |
2. 量词(Quantifiers)
量词用于控制匹配的次数,指定某个模式出现的次数范围:
量词 | 含义 |
---|---|
* | 匹配前面的模式零次或多次 |
+ | 匹配前面的模式一次或多次 |
? | 匹配前面的模式零次或一次 |
{n} | 匹配前面的模式正好 n 次 |
{n,} | 匹配前面的模式至少 n 次 |
{n,m} | 匹配前面的模式至少 n 次,至多 m 次 |
3. 字符集(Character Classes)
字符集是用来定义要匹配的字符范围或类别:
字符集 | 含义 |
---|---|
[abc] | 匹配字符 a 、b 或 c |
[^abc] | 匹配除 a 、b 、c 之外的任意字符 |
[a-z] | 匹配所有小写字母 |
[A-Z] | 匹配所有大写字母 |
[0-9] | 匹配所有数字 |
\d | 匹配任意数字,等价于 [0-9] |
\D | 匹配任意非数字字符,等价于 [^0-9] |
\w | 匹配任意字母、数字或下划线,等价于 [A-Za-z0-9_] |
\W | 匹配任意非字母、数字或下划线字符 |
\s | 匹配任意空白字符(空格、制表符、换行符等) |
\S | 匹配任意非空白字符 |
二、常见正则表达式例子
1. 匹配电子邮件地址
要匹配一个电子邮件地址,可以使用以下正则表达式:
[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+
解释:
[a-zA-Z0-9_.+-]+
:匹配邮箱名称部分,允许字母、数字、下划线、点号、加号、减号等字符,并且至少一个字符。@
:匹配固定的符号@
。[a-zA-Z0-9-]+
:匹配域名部分,允许字母、数字和短横线。\.
:匹配点号。[a-zA-Z0-9-.]+
:匹配域名后缀部分,允许字母、数字、点号和短横线。
2. 匹配电话号码(中国手机号码)
匹配中国的11位手机号码(以1开头):
1[3-9]\d{9}
解释:
1
:匹配以1
开头。[3-9]
:匹配第二位数字,范围为3
到9
。\d{9}
:匹配后面9位数字。
3. 匹配IP地址
IPv4 地址的匹配:
\b(?:\d{1,3}\.){3}\d{1,3}\b
解释:
\d{1,3}
:匹配1到3位数字。\.
:匹配点号。(?: ... )
:非捕获组,匹配点号和数字部分三次。\b
:匹配边界,确保是独立的IP地址。
4. 匹配日期(格式:YYYY-MM-DD)
\d{4}-\d{2}-\d{2}
解释:
\d{4}
:匹配4位数字(年份)。-
:匹配连字符。\d{2}
:匹配两位数字(月份和日期)。
5. 匹配URL地址
https?:\/\/(www\.)?[a-zA-Z0-9-]+\.[a-zA-Z]{2,}(/[a-zA-Z0-9#]+/?)*
解释:
https?
:匹配http
或https
。:\/\/
:匹配://
。(www\.)?
:可选匹配www.
。[a-zA-Z0-9-]+
:匹配域名部分。\.[a-zA-Z]{2,}
:匹配域名后缀,至少两位字母。(/[a-zA-Z0-9#]+/?)*
:匹配路径部分,可以出现零次或多次。
三、正则表达式在Python中的使用
在Python中,正则表达式由 re
模块提供支持。我们可以使用 re
模块来执行匹配、替换、查找等操作。
1. 导入 re
模块
import re
2. 常用方法
re.search()
:搜索字符串,返回第一个匹配的对象。re.match()
:从字符串的开头开始匹配,如果开头不匹配则返回None
。re.findall()
:返回所有匹配的字符串列表。re.sub()
:替换匹配的字符串。re.split()
:根据正则表达式分割字符串。
3. 实例代码
1. 匹配电子邮件地址
import re
text = "请联系: [email protected] 或 [email protected]"
email_pattern = r'[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+'
emails = re.findall(email_pattern, text)
print(emails) # 输出: ['[email protected]', '[email protected]']
2. 替换手机号码中的中间部分
将中国手机号的中间四位替换为****
,如 13812345678
替换为 138****5678
:
phone = "13812345678"
masked_phone = re.sub(r'(\d{3})\d{4}(\d{4})', r'\1****\2', phone)
print(masked_phone) # 输出: 138****5678
3. 分割字符串
使用正则表达式按空格或逗号分割字符串:
text = "apple, banana orange,grape"
split_text = re.split(r'[,\s]+', text)
print(split_text) # 输出: ['apple', 'banana', 'orange', 'grape']
4. 验证日期格式
验证日期是否符合 YYYY-MM-DD
格式:
date_pattern = r'^\d{4}-\d{2}-\d{2}$'
date = "2024-10-22"
if re.match(date_pattern, date):
print("日期格式正确")
else:
print("日期格式错误")
四、贪婪与非贪婪匹配
- 贪婪匹配:正则表达式默认是贪婪的,会尽可能多地匹配字符。
- 非贪婪匹配:通过在量词后加
?
,让正则表达式匹配尽可能少的字符。
例子
text = "<html><head><title>Title</title></head><body>Content</body></html>"
# 贪婪匹配,会匹配到从第一个 < 到最后一个 >
print(re.findall(r'<.*>', text))
# 输出: ['<html><head><title>Title</title></head><body>Content</body></html>']
# 非贪婪匹配,匹配最短的 < 和 > 之间的内容
print(re.findall(r'<.*?>', text))
# 输出: ['<html>', '<head>', '<title>', '</title>', '</head>', '<body>', '</body>', '</html>']
五、总结
正则表达式是一个非常强大的工具,适用于各种文本处理任务。从基础的匹配字符到复杂的模式提取,正则表达式提供了灵活的解决方案。尽管刚开始学习可能会显得复杂,但随着使用经验的积累,它将成为处理文本和数据不可或缺的工具。
下一步建议
- 通过更多实际案例练习正则表达式的应用,如日志分析、表单验证等。
- 学习如何在不同的编程语言中使用正则表达式,因为许多语言都支持正则表达式,如JavaScript、Java、Perl等。