正则表达式模块 re 字符使用详解
正则表达式,就是一个特殊的字符串。
本文包括正则表达式生成和使用两个部分:
- 正则表达式生成:字符的选用和组合(一、二、三、四)
- 正则表达式使用:拿生成的正则表达式,去匹配一个字符串中包含该正则表达式的部分(五)
一、字符类型(组合正则表达式)
- 普通字符(非元字符):在匹配字符串是只与自己匹配
- 14个元字符:. ^ $ ? + * \ | [ ] { } ( ) (8+6)
- 通配符. 转义字符\ 选择字符|
- 集合字符 [^-]
- 重复字符 *+?{,}
- 括号()
- 首尾字符^$
- 被转义的普通字符
十进制\d 数字字母\w 空白\s
大写时取补集
匹配字符时特殊字符,注意转义字符的使用
详述元字符作用
- 匹配单字符
- .匹配单个字符
- […] 字符集内的单个字符,
[abc]、所有十进制[0-9]、所有数字和字母[0-9a-zA-Z] - [^…]非字符集,排除该字符,取补集
[^abc]、 [^0-9]所有非十进制,[^\t\v\n\f\r]非空白字符
- 字符重复
- * 前一个字符零次或多次扩展
ab*表示a,abb等 - + 前一个字符1次或多次
- ? 前一个字符0次或1次
- {m} 扩展前一个字符m次
[2-9][0-9]{7}(总共七位数字) - {m,n} 扩展前一个字符m到n次
(关于字符重复都能用它写)- a* == a{0,infinity}
- a+ == a{1,infinity}
- a? == a{0,1}
- a{m} == a{m,m}
{m,n} 是贪婪匹配,会要重复次数最接近n的字符
破解:字符重复语句后面加一个问号?就可以不贪婪,例a+?、a{m,n}?
- * 前一个字符零次或多次扩展
- 匹配多字符
- | 或:
左右任意一个 abc|def - (…) 分组标记
内部可以使用|操作符
- | 或:
- 位置控制
- ^ 匹配开头,^abc表示abc且在一个字符串开头
- $ 匹配字符串结尾(行尾)
- 补充:可打印字符(非)
- \d 0-9 \D 所有非十进制的字符
- \w [a-z0-9A-Z] \W 作用相反,非字母数字字符
- \s 匹配空白符,等价于[\n\s\r\v\f] \S 非空白
- \b 匹配单词边界(非字母是单词边界) \B与\b作用相反
- \n 匹配已保存的子组 n是数字 ,()是获取组
- \A 匹配字符串的开始
- \Z 匹配字符串的结束
二、特殊的组合结构
- 正顺序组合αβ
- 选择组合α|β(既匹配又匹配)
- 星号α*(与α匹配的任意多个片段(0))
- () 中的当成一个组
三、经典的正则表达式语法
- ^[A-Za-z]+$ 由字母组成的str
- ^[A-Za=z0-9]+$ 或^-?\d+$ 由数字组成的字符串
- ^[0-9]?[1-9][0-9]*$ 正整数
- [1-9]\d{5} 6位邮政编码
- [\u4e00-\u9fa5] 中文字符
- \d{3}-\d{8}|d{4}-\d{7} 国内电话
- 25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d IPv4的地址
正则表达式的表示类型
- 原生字符串 R’‘或r’’:表示原来的内容
- 表达能力:正则表达式> 普通字符串>原生字符串
四、正则表达式的使用
两种匹配方法
- 普通匹配
re.search(“正则表达式”,“待匹配的字符串”) - compile和模式pattern
生成:p = re.compile(pattern)
使用:p.search(“待匹配的字符串”)p = re.compile('abc') ; m = p.search('AabcDabcE')
目的:假如某个正则表达式,需要用来匹配多个字符串,则可以先将该正则表达式编译(compile)成一个模型(pattern)。
常用的匹配函数
-
search (对字符串的模式搜索,返回re.Matchobject)
group 显示结果m = re.search('abc','AabcD');print(m.group())
-
findall (所有匹配,返回一个列表)(没有索引?for x in lst)
-
finditer (findall类似,返回一个迭代器,用完自动释放内存)
-
match (seach类似,只从头开始匹配,开头没有None)(\A)
-
fullmatch (从头开始,整个字符串)
-
split (用pattern作为分割符,maxsplit,返回一个list)
比普通字符串中的split强大,因为可以匹配 -
sub(pattern,repl,字符串)将字符串中pattern替代成repl
count参数,可以限制最大的替换次数phone = "2004-959-559";num = re.sub(r'\D',"",phone)
-
subn (类似sub,返回被替换后的字符串和替换次数,的元组)
-
enum (保存了所有的修饰符,all modifiers)
- re.I(ignorecase) 在search中可以忽略大小写
- re.S(dotall) 可匹配包括换行符在内的单个字符
- re.M(multilines) 多行,^$ 会受影响,启用时表示行首而不是串首。\A 和 \Z 不受影响,表示串首
-
group 对正则表达式进行分组,()最多99个分组,\n 访问
p = r'(A)(B(C))D' s = '1ABCD2' m = re.search(p,s) print(m.group()) print(m.group(1)) print(m.group(2)) # 几级运算 print(m.group(3))
- start(),end() 某序号分组的元素的开始和结束
- \n 表示第几个分组,从1开始:数左括号确定是第几组
- 对分组的引用,\1,\2 \g<name > P=name)等称为反向引用 ,是指在对字符串匹配的过程中,可以调用已匹配到的分组,进行匹配。
为组取名:?P<name> 调用时 \2 表示第2分组
s = 'To be, or not to be to' m1 = re.search(r'(\w+).*?\1',s,re.I) #其中\1表示,将(\w+)捕获的分组,反向引用用来匹配字符串 print(m1.group()) # To be, or not to print(m1.groups()) # ('To',)
- (?:…) 决定的分组,称为非捕获分组(内部为正则表达式)
m = re.search(r'(?P<FirstName>\w+)','MingWu') m.groups()
-
环视:
-
肯定前视 (?= ) 向前看未读的,前面有才要
s = '无名喜欢吃苹果和桔子' m = re.search(r'苹果(?=.+?桔子)',s) # .+? 表示通配符 print(m.group())
-
否定前视(?! )
-
肯定后视(?<=)
s = '无名喜欢吃苹果和桔子' m = re.search(r'(?<=苹果.)桔子',s) print(m.group())
-
否定后视(?<!)