正则表达式
动机
- 文本处理成为计算机常见工作之一
- 对文本内容搜索,定位,提取是逻辑比较复杂的工作
- 为了快速方便的解决上述问题,产生了正则表达式技术
定义
文本的高级匹配模式, 提供搜索, 替换, 本质由字符和特殊符号构成的字符串,
这个字符串即为正则表达式
匹配原理
通过普通字符和特殊含义的字符串, 来组成字符串,
用以描述一定的字符串规则, 比如重复, 位置, 来表达一种特定类型的字符串, 进而匹配
正则字符
通用
0 - 9 匹配所有字符 a - z 匹配所有小写字母 A - Z 匹配所有大写字母 A-Za-z 匹配所有字母
字符
. 换行符以外的任意\w 数字, 字母, 下划线, 汉字 [a-z]\s 空格\d 数字 [0-9]\b 单词边界 (数字,字母,下划线,汉字 与 其他字符交界位置)\W 非 数字, 字母, 下划线, 汉字 [^a-z]\S 非 空格\D 非 数字 [^0-9]\B 非 单词边界\n 换行符\t 制表符^ 开始位置$ 结束位置| 或 (匹配上即不在匹配,需要 长的放在前面 例如 abc|ab )
量词
* 0~n次+ 1~n次? 0~1次{n} n次{n,} n或 n+次{n,m} n~m 次
字符集
[] 匹配字符组中的字符[^] 匹配除了字符中的所有字符
分组
() 对整体进行 量词约束 ---> \1 \2 \3 进行位置选择(?:) 取消分组优先(?Ppattern) 命名分组 ----> \g \g 进行命名选择
注意点
- 一个正则中可以存在多个分组, 且分组可以嵌套
- 作用前提是整体的表达式能被匹配到内容才可以
- 未命名分组和命名分组是可以同时存在的, 未命名分组按照从外到内, 从左到右按照位置来用索引来命名
- 分组不要重叠, 且最好不要嵌套, 倘若出现说明设计存在巨大缺陷
转义
\ 被转义前加反斜线表示 匹配这一字符而不是用作正则表达式来处理r'' python 对字符串的不转义需要 用 r 来表示, 减去书写的麻烦
实例解析
# r""# s = "\\hello"# print(re.findall("\\\\\\w+", s))# print(re.findall(r'\\\w+', s))"""python 字符串 --> 正则 --> 目标字符串"\\$\\d+" \$\d+ "$100"r"\$\d+" \$\d+ "$100"* 为避免特殊字符串在字符串中使用时转义的麻烦, 使用 raw 字符串来表达正则表达式"""
总结
匹配单个字符
. [] [^] \d \D \w \W \s \S
匹配重复
* + ? {n} {n,m}
匹配位置
^ $ \A \Z \b \B
其他
| () \
贪婪 / 非贪婪匹配
- 默认 贪婪匹配 , 尽可能的往后匹配更多的内容
- 加 ? 改为 非贪婪匹配, 懒惰模式, 满足条件后不往后匹配更多内容
- 主要影响到的是重复匹配的操作符 * + ? {n} {n,m}
# 非贪婪匹配的运用# s = "ashb, asjdlab, asdadb"# print(re.findall(r"a.*b", s)) # ['ashb, asjdlab,asdadb']# print(re.findall(r"a.*?b", s)) # ['ashb', 'asjdlab', 'asdadb']
匹配原则
- 正确性 正确的匹配出目标字符串
- 精准性 除了目标内容, 尽可能不要存在多余内容
- 全面性 尽可能对目标字符串考虑全面, 做到不遗漏
Python re模块使用
compile
regex = compile(pattern,flags=0)
功能 生成正则表达式对象
参数
pattern 正则表达式
flags 功能标识,扩展正则匹配功能
返回值 正则对象
compile对象属性
- flags : flags值
- pattern : 正则表达式
- groups : 子组数量
- groupindex : 捕获组名与组序号的字典
findall
re.findall(pattern,string,flags=0)
功能 通过正则表达式匹配目标字符串内容
参数
pattern 正则表达式
string 目标字符串
返回值
返回匹配到的内容列表
如果正则表达式存在 子组 则只返回 子组对应的内容
sub
re.sub(pattern,replace,string,max,flags=0)
功能 使用指定字符串替换正则表达式匹配内容
参数
pattern 正则
replace 指定字符串
string 目标字符串
max 最多替换几处,默认全部替换
返回值 替换后的字符串
subn
re.subn()
功能参数 同sub,
返回值 多一个实际替换个数
finditer
re.finditer(pattern,string,flags=0)
功能 使用正则表达式匹配目标内容
参数
pattern 正则
string 目标字符串
返回值 迭代对象
fullmatch
re.fullmatch(pattern,string,flags=0)
功能 完全匹配某个目标字符串
参数
pattern 正则
string 目标字符串
返回值 匹配内容match object
match
re.match(pattern,string,flags=0)
功能 匹配某个目标字符串开始位置
参数
pattern 正则
string 目标字符串
返回值 匹配内容match object
match 对象
属性
pos 匹配的目标字符串开始位置endpos 匹配的目标字符串结束位置re 正则表达式string 目标字符串lastgroup 最后一组的名称lastindex 最后一组的序号
方法
span() 获取匹配内容的起止位置start() 获取匹配内容的开始位置end() 获取匹配内容的结束位置groupdict() 获取捕获组字典,组名为键,对应内容为值groups() 获取子组对应内容group(n = 0)
功能 获取match对象匹配内容
参数
默认为0表示获取整个match对象内容
如果是序列号或者组名则表示获取对应子组内容
返回值 匹配字符串
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
import reimport sysport = sys.argv[1]f = open('1.txt')# 找到端口所在的对应段落while True: data = '' for line in f: if line != '\n': data += line else: break if not data: print("No PORT") break # 通过首单词比对是否为目标段 try: PORT = re.match(r'\S+', data).group() except Exception: continue if port == PORT: # pattern=r"[0-9a-f]{4}\.[0-9a-f]{4}\.[0-9a-f]{4}" pattern = r"address is ((\d{1,3}\.){3}\d{1,3}/\d+|Unknown)" address = re.search(pattern, data).group(1) print(address) breakf.close()
search
re.search(pattern,string,flags=0)
功能 匹配目标字符串第一个符合内容
参数
pattern 正则
string 目标字符串
返回值 匹配内容match object
flags
扩展丰富正则表达式的匹配功能
可调用的函数
re.compile,re.findall,re.search....
常用 flag
A == ASCII 元字符只能匹配ascii码I == IGNORECASE 匹配忽略字母大小写S == DOTALL 使 . 可以匹配换行M == MULTILINE 使 ^ $可以匹配每一行的开头结尾位置X == VERBOSE 为正则添加注释
使用多个flag
flags = re.I | re.A
实例
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
import re # 只匹配ascii字符# regex = re.compile(r'\w+',flags=re.A)# 忽略字母大小写# regex = re.compile(r'[A-Z]+',flags=re.I)# . 可以匹配换行# regex = re.compile(r'.+',flags=re.S)# 匹配每一行开始位置# regex = re.compile(r'^北京',flags=re.M)# 为正则添加注释pattern = r'''[A-Z][a-z]* #匹配第一个单词\s+\w+\s+ #匹配空行和第二个单词\w+ #匹配汉字'''regex = re.compile(pattern,flags=re.X)s = '''Welcome to北京'''l = regex.findall(s)print(l)
split
split(pattern, string, maxsplit=0, flags=0)
功能 实现对字符串的正则切割, 可以进行多个分隔符进行切割
参数 正则, 被切割字符串, 保留个数, flag
import res = "sda.sda'sda/sda1adsa-ada.sad"print(re.split("[./'-]+", s))# ['sda', 'sda', 'sda', 'sda1adsa', 'ada', 'sad']
import res = "sda.sda'sda/sda1adsa-ada.sad"print(re.split("[./'-]+", s, maxsplit=3))# ['sda', 'sda', 'sda', 'sda1adsa-ada.sad']