Python学习笔记:正则表达式基础入门指南
一.正则表达式简介
正则表达式(Regex)用来查找和匹配字符串中的模式。可以把它看作是一种“搜索”工具,帮助找到特定的字符或字符串,表1给出一些常见的特殊字符应用:
表1 特殊字符在正则化表达式的应用
字符 |
作用 |
. |
匹配除换行符以外的任何单个字符 |
\d |
匹配任何数字字符 |
\D |
匹配任何非数字字符 |
\w |
匹配任何字母数字字符(包括下划线) |
\W |
匹配任何非字母数字字符(不包括下划线) |
\s |
匹配任何空白字符(包括空格、制表符、换行符等) |
\S |
匹配任何非空白字符 |
^ |
匹配字符串的开始位置 |
$ |
匹配字符串的结束位置 |
* |
匹配前面的字符0次或多次 |
+ |
匹配前面的字符1次或多次 |
? |
匹配前面的字符0次或1次 |
{m} |
匹配前面的字符m次 |
{m,n} |
匹配前面的字符至少m次,至多n次 |
一般来说,通常的代码可以写作:
pattern = r'\b\w+\b'
r
前缀让Python将字符串中的反斜杠视为普通字符,而不是转义符
二.Re模块
2.1Re.match()函数
re.match()函数从字符串起始位置开始匹配
re.match(pattern,string,flags=0)
其中pattern是匹配的正则表达式,string是待匹配的字符串,flags是控制位,用来控制匹配方式。
若string中的字符串和pattern中的正则表达式匹配,就返回匹配值,输出开始和起始位置。
下面给出匹配示例:
import re
print(re.match('a','abstract').span())
print(re.match('ab','abstract').span())
print(re.match('b','abstract'))
使用相关字符去匹配字符串,得到结果输出如下:
(0, 1)
(0, 2)
None
2.2Re.search()函数
Re.search函数会匹配整个字符串,若string中的字符串和pattern中的正则表达式匹配,就返回匹配值
re.search(pattern,string,flags=0)
匹配结果和match函数相同,成功则返回输出位置,失败则返回None
import re
print(re.search('a','abstract').span())
print(re.search('ab','abstract').span())
print(re.search('b','abstract').span())
print(re.search('rac','abstract').span())
print(re.search('e','abstract'))
得到结果如下:
(0, 1)
(0, 2)
(1, 2)
(4, 7)
None
2.3Re.sub()函数
re.sub()函数用以替换字符串的匹配项
re.sub(pattern, repl, string)
pattern是要匹配的正则表达式模式,repl是替换的内容,可以是一个字符串或函数,string是被处理的原始字符串。
2.4re.compile()函数
re.compile(pattern, flags=0)
re.compile() 函数作用是可以将编译后的正则表达式对象存储在一个变量中,并多次使用它进行匹配
三.贪婪模式与非贪婪模式
贪婪模式会尽可能多地匹配字符,直到整个正则表达式都能匹配成功为止。
* |
匹配前面的字符0次或多次 |
+ |
匹配前面的字符1次或多次 |
? |
匹配前面的字符0次或1次 |
{m,n} |
匹配前面的字符至少m次,至多n次 |
非贪婪模式与贪婪模式相反,它会尽可能少地匹配字符
比较贪婪模式,非贪婪模式会多一个字符"?"区分
* |
匹配前面的字符0次或多次,但尽可能少地匹配 |
+ |
匹配前面的字符1次或多次,但尽可能少地匹配 |
? |
匹配前面的字符0次或1次,但尽可能少地匹配 |
{m,n} |
匹配前面的字符至少m次,至多n次,但尽可能少地匹配 |
四.相关练习
4.1解析北美地区电话号码
电话号码有一个3位数的区号和一位7位数的号码组成(这个7位数有分成一个3位的局号和一个4位的路号,局号和路号之间使用连字符分隔) 每位电话号码可以是任意数字,但是区号和局号的第一位数字不能是0或1。实际书写号码是往往会把区号写在括号里面,或者将区号使用连字符和后面的局号连接起来。例如:(313)555-1234或313-555-1234,有时候在括号你里面会包含空格。例如:(313 )555-1234
解析:开始和结束使用^和$;区号的括号可选可不选,使用\(?和\)?匹配;由于区号和局号首位数字不能为0或1,使用[2-9]匹配;对于后续位数数字使用\d{m}表示匹配m次数字;由于括号里面可能包含空格,使用\s?匹配,若是多位空格则需把?改为*,本题应只为?;后面可能没有括号()而是直接使用"-"符号,使用-?表示匹配,同理后续局号和路号的处理也用[2-9]和\d{m}处理。
pattern=r'^\(?[2-9]\d{2}\s?\)?-?[2-9]\d{2}-\d{4}$'
测试
import re
pattern=r'^\(?[2-9]\d{2}\s?\)?-?[2-9]\d{2}-\d{4}$'
numbers = [
"(313)555-1234",
"(810 )555-1234",
"248-555-1234",
"055-123-1234",
"155-123-1234",
"555 123 1234"
]
for i in numbers:
if re.match(pattern, i):
print(f"{i} 是有效的电话号码。")
else:
print(f"{i} 不是有效的电话号码。")
输出
(313)555-1234 是有效的电话号码。
(810 )555-1234 是有效的电话号码。
248-555-1234 是有效的电话号码。
055-123-1234 不是有效的电话号码。
155-123-1234 不是有效的电话号码。
555 123 1234 不是有效的电话号码。
参考
1.正则表达式指南 — Python 3.13.3 文档
2.解析各类电话号码、邮政编码及邮箱地址的正则表达式-CSDN博客
作者:孜宸润泽