正则表达式
应用场景
- 特定规律字符串的查找替换切割等
- 邮箱格式、URL、IP等的校验
- 爬虫项目中,特定内容的提取
使用原则
- 只要是能够使用字符串函数解决的问题,就不要使用正则
- 正则的效率较低,还会降低代码的可读性
- 世界上最难理解的三样东西:医生的处方、道士的神符、码农的正则
- 提醒:正则是用来写的,不是用来读的;在不知道功能的情况下,不要试图阅读别人的正则。
基本使用
-
说明:正则的解析处理是由
re
模块完成 -
相关函数:
- match:从开头进行匹配,匹配到就返回正则结果对象,没有就返回None
- search:从任意位置匹配,匹配到一次就返回,没有就返回None
import re # 只从开头匹配,找到返回一个正则结果对象,没有找到返回None # m = re.match('abc', 'abcsdhasdasjabcweuqo') # 全部匹配,只要找到就停止并返回 m = re.search('abc', 'sdhabcsdasjabcweuqo') if m: # 提取匹配到的内容 print(m.group()) # 获取匹配位置 print(m.span())
- findall:全局匹配,返回匹配到的结果列表,没有时返回空列表
# 匹配所有内容,返回匹配结果组成的列表,若没有则返回空列表 f = re.findall('abc', 'qwsdhaslabcsadjlasdoiabcdakls') if f: print(f) print(type(f))
- compile:生成正则表达式对象
# 生成正则表达式对象,用于正则匹配 c = re.compile('hello') # 从开头进行匹配 # m = c.match('hellosdsjldkabc') # 从任意位置匹配 m = c.search('shdjkhelloaskjdha') if m: print(m.group()) # 匹配所有 f = c.findall('helloasjdhakhello') if f: print(f)
将正则的匹配分两步完成:先创建正则对象,然后通过对象的match、search、findall方法完成匹配
正则规则
-
单个字符:
普通字符:简单来说就是一对一的完全匹配 []:中间的任意一个字符 [a-z]:a~z之间的字符(所有小写字母) [0-9]:0~9之间的字符(所有数字) [A-Z0-9]:所有的大写字母和数字 [^abc]:除abc外的所有字符 . :匹配' '以外的任意字符 d:所有的数字,等价于[0-9] D:所有的非数字,等价于[^0-9] w:所有的数字、字母(中文)、下划线等(就是字) W:所有的非字字符(w的取反) s:所有的空白字符( 、 、 、空格等) S:所有的非空白字符 :词边界匹配(开头、结尾、标点、空格) B:非词边界匹配
-
次数控制
*:前面的字符出现任意次 +:前面的字符出现至少一次 ?:前面的字符出现至多一次 {m}:指定次数,m表示出现的次数 {m,}:至少指定次数 {m,n}:指定范围内的次数,m到n次之间 {,n}:至多n次,相当于{0,n}
正则的匹配默认都是贪婪的(最大限度的匹配)
-
边界限定
- ^:以指定的内容开头
- $:以指定的内容结尾
- 示例
import re # 以指定的内容开头 # c = re.compile(r'^abc') # 以指定的内容结尾 c = re.compile(r'kas$') s = c.search('abcsdhkas') if s: print(s.group())
-
优先级控制
- |:表示或,它拥有最低的优先级
- ():用于表示一个整体,明确的指定优先级
- 示例:
import re c = re.compile(r'a(hello|world)b') s = c.search('aworldb') if s: print(s.group())
-
分组匹配
- 说明:()不但可以作为一个整体,还可以进行分组匹配
- 示例1:
import re c = re.compile(r'(d+)([a-z]+)(d+)') s = c.search('shd327sjahdajhsd87892ehawksd') if s: print(s.group()) # 默认就是全部的匹配内容,等价于上式 print(s.group(0)) # 第一个()匹配到的内容 print(s.group(1)) print(s.group(2)) print(s.group(3)) print(s.span()) print(s.span(0)) print(s.span(1)) print(s.span(2)) print(s.span(3))
- 示例2:给分组起名字
import re # 固定匹配 # c = re.compile(r'<div><a>w+</a></div>') # 1表示前面第一个小括号匹配的内容 # c = re.compile(r'<([a-z]+)><([a-z]+)>w+</2></1>') # 给()起名字 c = re.compile(r'<(?P<goudan>[a-z]+)><(?P<ergou>[a-z]+)>w+</(?P=ergou)></(?P=goudan)>') s = c.search('<div><a>百度一下</a></div>') if s: print(s.group())
-
贪婪匹配
- 贪婪:最大限度的匹配叫贪婪。正则的匹配默认是贪婪。
- 非贪婪:只要满足匹配条件,能少匹配就少匹配;通过可以使用'?'进行取消贪婪
- 示例:
import re # 取消任意多次的贪婪 # c = re.compile(r'a.*?b') # 取消至少一次的贪婪 c = re.compile(r'a.+?b') s = c.search('abdhsadjbsdjabs') if s: print(s.group())
-
匹配模式
- 说明:所谓模式就是对匹配的原则进行整体的修饰
- 示例:
import re # 忽略大小写的匹配 # c = re.compile(r'hello', re.I) # s = c.search('Hello world') # 进行多行匹配,默认单行匹配 # c = re.compile(r'^hello', re.M) # s = c.search('world hello') # 做为单行处理 或 让 . 能够匹配 c = re.compile(r'<div>.*?</div>', re.S) # string = '<div>hello</div>' string = '''<div> hello </div>''' s = c.search(string) if s: print(s.group())
-
字符转义
- 若匹配正则语法中的特定字符都需要进行转义
- 正则字符串会被处理两次,python中处理一次,re模块会在处理一次
- 若不想考虑字符的转义问题,可以在书写正则字符串时前面加一个字符'r'
- 添加'r'之后,在python不会再进行任何转义,只需在与正则语法相关的字符前加''即可让其使用原有意义