正则表达式
应用场景
特定规律字符串的查找替换切割等
邮箱格式, 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 外的所有字符
. : 匹配'\n'以外的任意字符
\d: 所有的数字, 等价于[0-9]
\D: 所有的非数字, 等价于[^0-9]
\w: 所有的数字, 字母(中文), 下划线等(就是字)
\W: 所有的非字字符(\w 的取反)
\s: 所有的空白字符(\n,\t,\t, 空格等)
\S: 所有的非空白字符
\b: 词边界匹配(开头, 结尾, 标点, 空格)
\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 \nhello')
- # 做为单行处理 或 让 . 能够匹配 \n
- 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 不会再进行任何转义, 只需在与正则语法相关的字符前加''即可让其使用原有意义
来源: https://www.cnblogs.com/swjblog/p/9677816.html