这一节了解一下Python中的模式匹配与正则,在Python里,模式匹配就是"按某种规则去找字符串";正则表达式就是用来描述这种规则的"特殊语法",简单总结一些模式匹配与正则:
API:
1.import re 导入正则模块,所有正则相关对象、函数都来自该模块,不导入会报NameError。
python
import re
脚本开头写import re,后续调用re.compile()。
2.re.compile(r'正则模式')编译正则对象,接收原始字符串正则模式,编译返回Regex正则对象;原始字符串r''避免反斜杠转义冲突。
python
regex_obj = re.compile(r'匹配模式')
phoneRegex = re.compile(r'\d{3}-\d{3}-\d{4}')
3.Regex对象.search(文本)方法,在传入字符串查找第一个匹配项,找到返回Match匹配对象,找不到返回None。只找首次匹配。
python
match_obj = regex_obj.search("待检索文本")
mo = phoneRegex.search('My phone is 415-555-1234')
4.Match对象.group()获取完整匹配文本,不传参数返回整个正则完整匹配字符串;参数0等价无参。
python
result_str = match_obj.group()
mo.group()得到'415-555-1234'
5.Match对象.group(n)获取指定分组匹配,传入数字n,获取第n个括号分组匹配到的子串;分组序号从1开始。
python
sub_str = match_obj.group(分组编号)
mo.group(1)获取电话号码的区号分组。
6.Match对象.groups()获取全部分组元组,复数groups(),返回所有括号分组匹配内容组成的元组,支持多重解包赋值。
python
tuple_res = match_obj.groups()
area,num = mo.groups()
7.Regex对象.findall(文本)查找全部匹配,查找字符串所有匹配;无分组返回字符串列表;存在分组返回元组列表。不会返回Match对象。
python
all_list = regex_obj.findall("待检索文本")
phoneRegex.findall('A:111-222-3333 B:444-555-6666')
8.Regex对象.sub(替换文本,原文本)查找替换,找到所有匹配的内容,替换为指定字符串,返回替换完成新字符串。
python
new_text = regex_obj.sub('替换内容','原始文本')
namesRegex.sub('CENSORED','Agent Alice meet Agent Bob')
9.sub替换反向引用\1 \2,sub第一个替换字符串内,\1代表引用正则第1分组捕获内容,复用匹配到的子串。
python
new_text = regex_obj.sub(r'\1****',source_text)
agentRegex.sub(r'\1****','Agent Alice')输出A****
10.管道元字符 | 匹配多选一,匹配|左右任意一个表达式;括号内可以做局部多选。匹配最先出现的项。
python
regex_obj = re.compile(r'A|B')
heroRegex = re.compile(r'Batman|Superman')
11.问号元字符 ? 分组可选匹配(第一层含义),(xxx)?代表前面分组可以出现0次或者1次,该分组是可选。
python
re.compile(r'(part)?text')
re.compile(r'(\d{3}-)?\d{3}-\d{4}') 区号可选。
12.问号元字符?非贪心修饰(第二层含义),放在重复元字符* + {m,n}后面,开启非贪心,匹配尽可能短文本。
python
re.compile(r'.*?')
re.compile(r'<.*?>')最短匹配尖括号内容。
13.星号元字符 *零次或多次,pattern*前面分组匹配0次或者无限多次,可以完全不出现。
python
re.compile(r'(wo)*man')
batRegex = re.compile(r'Bat(wo)*man')匹配Batman、Batwoman。
14.加号元字符 + 一次或多次,pattern+前面分组至少出现1次,不可以完全缺失。
python
re.compile(r'(wo)+man')
re.compile(r'Bat(wo)+man')不能匹配Batman。
15.花括号{n}固定重复次数,(pat){n},该分组严格重复n次。
python
re.compile(r'(Ha){3}')
匹配HaHaHa。
16.花括号{n,m}次数范围,{n,m}分组最少n次、最多m次;{n,}大于等于n;{,m}小于等于m。正则默认贪心。
python
re.compile(r'(Ha){3,5}')
匹配3~5次Ha。
- 数字字符分类 \d 和 \D,\d匹配任意0‑9数字;\D匹配任意非数字字符。
python
re.compile(r'\d+')
re.compile(r'\d{3}-\d{3}-\d{4}')电话号码。
18.单词字符分类\w和\W,\w匹配字母、数字、下划线;\W匹配除以上之外字符。
python
re.compile(r'\w+')
匹配单词标识符。
19.空白字符分类\s和\S,\s匹配空格、制表、换行空白;\S匹配非空白字符。
python
re.compile(r'\d+\s\w+')
匹配'12 drummers'这类字符串。
20.自定义字符类 abc...方括号,方括号内部自定义字符集合,匹配括号内任意一个字符;支持a‑z范围;括号内部. * ?不需要转义。
python
re.compile(r'[aeiouAEIOU]')
vowelRegex.findall(text)提取全部元音字母。
21.取反字符类 \^...,方括号开头写^,匹配所有不在集合内的任意字符。
python
re.compile(r'[^aeiouAEIOU]')
匹配所有非元音字符。
22.脱字符^匹配字符串开头,^pattern整个字符串必须以此模式开头。
python
re.compile(r'^Hello')
只匹配以Hello开头的文本。
23.美元符匹配字符串结尾,pattern字符串必须以此模式结尾;^...$表示整串完全匹配。
python
re.compile(r'\d+$')
wholeNumRegex = re.compile(r'^\d+$')整串必须全数字。
24.句点通配符 .匹配任意字符(除换行),.匹配除换行符以外单个任意字符;只匹配1个字符;匹配真实句点需要\.转义。
python
re.compile(r'.at')
匹配cat、hat、mat。
25.点星.*匹配任意多字符(贪心),"."任意单字符 +*零次多次,匹配尽可能长文本,不包含换行。
python
re.compile(r'First: (.*) Last: (.*)')
提取First、Last后面的内容。
26.标志位 re.IGNORECASE / re.I忽略大小写,作为compile第二个参数,匹配时不区分大写小写字母。
python
regex_obj = re.compile(r'pattern', re.IGNORECASE)
robocop = re.compile(r'robocop', re.I)
27.标志位re.DOTALL让.可以匹配换行符,开启后.通配符可以匹配换行\n字符。
python
regex_obj = re.compile(r'.*', re.DOTALL)
一次性跨多行抓取全部文本。
28.标志位re.VERBOSE详细模式,支持注释,正则字符串可以换行、写#注释,忽略正则内部多余空格;适合复杂长正则。使用三重引号多行原始字符串。
python
regex_obj = re.compile(r'''多行正则''', re.VERBOSE)
教材电话号码多行带注释正则。
29.标志位组合|按位或,compile第二个参数只能接收一个标志,多个标志用管道|进行组合。
python
re.compile(r'xxx', re.IGNORECASE | re.DOTALL | re.VERBOSE)
同时开启忽略大小写、点匹配换行、详细注释模式。
栗子:
python
import re
def check_strong_password(pwd):
if len(pwd) < 8:
return False
upper_re = re.compile(r'[A-Z]')
lower_re = re.compile(r'[a-z]')
num_re = re.compile(r'\d')
has_upper = upper_re.search(pwd) is not None
has_lower = lower_re.search(pwd) is not None
has_digit = num_re.search(pwd) is not None
return has_upper and has_lower and has_digit
test_list = ["Abc123", "Abcdef123", "abcdef123", "ABCDEF123"]
for pw in test_list:
if check_strong_password(pw):
print(f"{pw} 是强口令")
else:
print(f"{pw} 口令强度不满足")
demo2
python
import re
import pyperclip
phoneRegex = re.compile(r'''(
(\d{3}|\(\d{3}\))? # 区号 可选
(\s|-|\.)? # 分隔符
(\d{3}) # 中间3位数字
(\s|-|\.) # 分隔符
(\d{4}) # 后4位数字
(\s*(ext|x|ext.)\s*(\d{2,5}))? # 分机号可选
)''', re.VERBOSE)
emailRegex = re.compile(r'''(
[a-zA-Z0-9._%+-]+
@
[a-zA-Z0-9.-]+
(\.[a-zA-Z]{2,4})
)''', re.VERBOSE)
clip_text = pyperclip.paste()
results = []
for groups in phoneRegex.findall(clip_text):
phone = '-'.join([groups[1], groups[3], groups[5]])
if groups[8] != '':
phone += ' x' + groups[8]
results.append(phone)
for groups in emailRegex.findall(clip_text):
results.append(groups[0])
if len(results) > 0:
output_text = '\n'.join(results)
pyperclip.copy(output_text)
print("已复制到剪贴板:")
print(output_text)
else:
print("未找到手机号或邮箱地址")