14. 正则表达式
14.1. 概述
14.1.1. 概念
- Regular Expression
- 一种文本模式,描述在搜索文本时要匹配的一个或多个字符串
14.1.2. 典型场景
- 数据验证
- 文本扫描
- 文本提取
- 文本替换
- 文本分割
14.1.3. 语法
- 字面值
• 普通字符
• 需转义
• \
• ^
• $
• .
• |
• ?
• *
• +
• ()
• []
• {}
- 元字符
14.1.4. 匹配
- 单字,预定义元字符
• . 除\n外的所有字符
• \d 数字,等同于[0-9]
• \D 费数字,等同于[^0-9]
• \s 空白字符 \t\n\r\f\v
• \S 非空白字符 [^\t\n\r\f\v]
• \w 字母数字字符[a-zA-Z0-9_]
• \W 非字母数字字符[^a-zA-Z0-9_]
- 批量备选
• | yes|no
- 量词(字符,元字符,字符集如何重复)
• ? 0或1次
• * 0或多次
• + 1或多次
• 特定
• {n,m} 范围次数
• {n} n次
• {n,} 至少n次
- 贪婪与非贪婪
• 贪婪(默认):尽量匹配最大范围结果
• 非贪婪
• 尽量匹配最小的范围结果
• 方法:量词后追加?
• 举例:
• ??
• *?
• +?
- 边界匹配
• ^ 行首
• $ 行尾
• \b 单词边界
• \B 非单词边界
• \A 输入开头
• \Z 输入结尾
• 注:或因上下文差异有不同表现
14.2. Python正则
14.2.1. 模块
- import re
14.2.2. RegexObject 正则对象
- 模式对象,表现编译后的正则表达式(编译为字节码并缓存)
- 编译
• re.compile(r'模式')
• 示例1
1 import re 2 3 # Case 1: 4 text = "Tom is 8 years old. Mike is 25 years old." 5 6 # patten = re.compile('\d+') 7 # patten.findall(text) 8 9 # Same functions 10 11 # re.findall('\d+',text)
• 示例2
1 import re 2 3 # Case 2: 4 5 s = "\\author:Tom" 6 patten = re.compile('\\author') 7 patten.findall(s) 8 9 # output is [] and the code needs to edit as follows: 10 11 s = "\\author:Tom" 12 patten = re.compile('\\\\author') 13 patten.findall(s) 14 15 # Output is ['\\author']
- .findall()
• 查找所有非重叠匹配项
• 查找所有非重叠匹配项
• 返回list
• 示例1
# Case 3: text = 'Tom is 8 years old. Mike is 23 years old. Peter is 87 years old.' patten = re.compile(r'\d+') patten.findall(text) # Output is ['8', '23', '87']
• 示例2
# Case 4: text = 'Tom is 8 years old. Mike is 23 years old. Peter is 87 years old.' p_name = re.compile(r'[A-Z]\w+') p_name.findall(text) # Output is ['Tom', 'Mike', 'Peter']
- .match(string[,pos[,endpos]])
• 匹配,仅从起始位置
• 返回 Match Object
• 示例1
# Case 5: text = '<html><head></head><body></body></html>' pattern = re.compile(r'<html>') pattern.match(text) # Output is <re.Match object; span=(0, 6), match='<html>'>
• 示例2:加了一个空格
# Case 6: text = ' <html><head></head><body></body></html>' #加了一个空格 pattern = re.compile(r'<html>') pattern.match(text) # Output is blank
- .search(string[,pos[,endpos]])
• 任意位置搜索
• 返回 Match Object
• 示例:加了一个空格
# Case 7: text = ' <html><head></head><body></body></html>' #加了一个空格 pattern = re.compile(r'<html>') pattern.search(text) # Output is <re.Match object; span=(1, 7), match='<html>'>
- .finditer()
• 查找所有匹配项
• 返回包括 Match Object元素的迭代器
• 示例:可对结果做遍历
# Case 8: text = 'Tom is 8 years old. Mike is 23 years old. Peter is 87 years old.' p1 = re.compile(r'\d+') it = p1.finditer(text) for m in it: print(m) # Output is # <re.Match object; span=(7, 8), match='8'> # <re.Match object; span=(28, 30), match='23'> # <re.Match object; span=(51, 53), match='87'>
14.2.3. MatchObject 匹配对象
- 表现被匹配的模式
- .group()
• 参数为0或空返回整个匹配
• 有参时返回特定分组匹配细节
• 参数也可以是分组名称
- .groups()
• 返回包含所有子分组的元组
- .start() 返回特定分组的起始索引
- .end() 返回特定分组的终止索引
- 上述方法的示例1
import re text = "Tom is 8 years old. Jerry is 23 years old." pattern = re.compile(r'\d+') pattern.findall(text) # Output is : ['8', '23'] pattern = re.compile(r'(\d+).*?(\d+)') m = pattern.search(text) m # Output is : <re.Match object; span=(7, 31), match='8 years old. Jerry is 23'> m.group() # Output is : '8 years old. Jerry is 23' m.group(0) # Output is : '8 years old. Jerry is 23' m.group(1) # Output is : '8' m.group(2) # Output is : '23' m.start(1) # Output is : 7 m.end(1) # Output is : 8 m.start(2) # Output is : 29 m.end(2) # Output is : 31 m.groups() # Output is : ('8', '23')
- .span() 返回特定分组的起止索引元组
- .groupdict() 以字典表形式返回分组名及结果
- 示例2
# Case 2: import re pattern = re.compile(r'(\w+) (\w+)') text = "Beautiful is better than ugly." pattern.findall(text) # Output is : [('Beautiful', 'is'), ('better', 'than')] it = pattern.finditer(text) for m in it: print(m.group()) # Output is : # Beautiful is # better than
14.3. Group 编组
14.3.1. 场景
- 从匹配模式中提取信息
- 创建子正则以应用量词
• 示例
import re re.search(r'ab+c','ababc') #Output is : <re.Match object; span=(2, 5), match='abc'> re.search(r'(ab)+c','ababc') #Output is : <re.Match object; span=(0, 5), match='ababc'>
- 限制备选项范围
• 示例
re.search(r'Center|re','Center') #Output is : <re.Match object; span=(0, 6), match='Center'> re.search(r'Center|re','Centre') #Output is : <re.Match object; span=(4, 6), match='re'> re.search(r'Cent(er|re)','Centre') #Output is : <re.Match object; span=(0, 6), match='Centre'> re.search(r'Cent(er|re)','Center') #Output is : <re.Match object; span=(0, 6), match='Center'>
- 重用正则模式中提取的内容
• 示例
re.search(r'(\w+)+ \1','hello world') #Output is : Blank re.search(r'(\w+)+ \1','hello hello world') #Output is : <re.Match object; span=(0, 11), match='hello hello'>
14.3.2. 申明
- (模式)
- (?P<name>模式)
• 示例
text = "Tom:98" pattern = re.compile(r'(?P<name>\w+):(?P<score>\d+)') m = pattern.search(text) m.group() #Output is : 'Tom:98' m.group(1) #Output is : 'Tom' m.group('name') #Output is : 'Tom' m.group('score') #Output is : '98'
14.3.3. 引用
- 匹配对象内 m.group('name')
- 模式内 (?P=name)
- 变现内 \g<name>
- 字符串操作
14.3.4. 应用
• .split(string, maxsplit=0)
• 分割字符串
• 示例
import re text = 'Beautiful is better than ugly.\nExplicit is better than implicit.\nSimple is better than complex.' p = re.compile(r'\n') p.split(text) #Output is : #['Beautiful is better than ugly.', # 'Explicit is better than implicit.', # 'Simple is better than complex.'] re.split(r'\W','Good Morning') #Output is : ['Good', 'Morning'] re.split(r'\n',text,2) #Output is : #['Beautiful is better than ugly.', # 'Explicit is better than implicit.', # 'Simple is better than complex.'] re.split(r'\n',text,1) #Output is : #['Beautiful is better than ugly.', # 'Explicit is better than implicit.\nSimple is better than complex.']
• .sub(repl,string,count=0)
• 替换字符串
• 示例
ords = 'ORD000\nORD001\nORD003' re.sub(r'\d+','-',ords) #Output is : 'ORD-\nORD-\nORD-' re.sub(r'([A-Z]+)(\d+)','\g<2>-\g<1>',ords) #Output is :'000-ORD\n001-ORD\n003-ORD' text = 'Beautiful is *better* than ugly.' re.sub(r'\*(.*?)\*','<strong></strong>',text) #Output is : 'Beautiful is <strong></strong> than ugly.' re.sub(r'\*(.*?)\*','<strong>\g<1></strong>',text) #Output is : 'Beautiful is <strong>better</strong> than ugly.'
• .subn(repl,string,count=0)
• 替换并返回替换数量
• 示例
re.subn(r'([A-Z]+)(\d+)','\g<2>-\g<1>',ords) #Output is : ('000-ORD\n001-ORD\n003-ORD', 3)
- 编译标记
• 改变正则的默认行为
• re.I 忽略大小写
• 示例
text = 'Python python PYTHON' re.search(r'python',text) #Output is : <re.Match object; span=(7, 13), match='python'> re.findall(r'python',text) #Output is : ['python'] re.findall(r'python',text,re.I) #Output is : ['Python', 'python', 'PYTHON']
• re.M 匹配多行
• 示例
import re re.findall(r'^<html>','\n<html>') #Output is : [] re.findall(r'^<html>','\n<html>',re.M) #Output is : ['<html>']
• re.S 指定“.”匹配所有字符,包括\n
• 示例
re.findall(r'\d(.)','1\ne') #Output is : [] re.findall(r'\d(.)','1\ne',re.S) #Output is : ['\n']
• ... ...
- 模块级别操作
• re.purge() 清理正则缓存
• 示例
re.purge()
• re.escape() 逃逸字符
• 示例
re.findall(r'^','^python^') #Output is : [''] re.findall(re.escape('^'),'^python^') #Output is : ['^', '^']
15. 系统工具
15.1. 概念
15.1.1. 命令行工具
15.1.2. Shell脚本
15.1.3. 系统管理
15.2. 系统模块
15.2.1. sys
- 提供一组功能映射Python运行时的操作系统
- 提供跨平台可移植的操作系统编程接口
- os.path 提供文件及目录工具的可移植编程接口
- sys.platform
- sys.version
- sys.path
- sys.modules
- sys.exc_info() 获取最后一次异常细节
15.2.2. os
15.3. sys
15.3.1. 平台与版本
15.3.2. 观察异常细节
• 示例
import sys import traceback try: raise KeyError except: print(sys.exc_info()) # Output is: (<class 'KeyError'>, KeyError(), <traceback object at 0x00000200332E6808>)
- traceback.print_tb(sys.exc_info()[2])
• 示例
traceback.print_tb(sys.exc_info()[2]) # Output is: File "<ipython-input-70-1bc1bfcd4795>", line 5, in <module> raise KeyError
15.3.3. 命令行参数
- sys.argv
- sys.stdin 标准输入流 默认等同于 input()
- sys.stdout 标准输出流 默认等同于 print()
- sys.stderr 标准错误流
- os.environ
- .getcwd() 获取当前工作目录
- .listdir(path) 列举目录内容
- .chdir(path) 改变工作目录
- .getpid() 获取当前进程ID
- .getppid() 获取当前父进程ID
- .system() Python脚本中运行shell命令
- .popen() 运行命令并连接输入输出流
- .mkdir('目录名') 创建目录
- .rmdir('目录名') 删除目录
- .rename('旧名','新名') 改名
- .remove('文件名') 删除文件
- .sep 分隔符
- .pathsep 路径分隔符
- .curdir 相对当前目录符号
- .pardir 相对上级目录符号
- .isdir(path) 是否目录
- .isfile(path) 是否文件
- .exists(path) 是否存在
- .split(path) 拆分路径
- .splitext(path) 拆分路径扩展名
- .join() 连接路径
- .normpath() 标准化路径
- .abspath() 绝对化路径