python模块详解 | re
前言
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。
Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。
正则并不是python独有的,re 模块使 Python 语言拥有全部的正则表达式功能。
便于测试自己写的正则,可以使用开源中国提供的正则表达式测试工具 https://tool.oschina.net/regex/
python学习文档 - https://docs.python.org/zh-cn/3/library/re.html
匹配规则
匹配单个字符:
模式 | 描述 |
---|---|
\w | 匹配字母、数字、下划线 |
\W | 匹配非字母、数字、下划线 |
\s | 匹配任意空白字符,等价于 [\t\n\r\f] |
\S | 匹配任意非空字符 |
\d | 匹配任意数字,等价于 [0-9] |
\D | 匹配任意非数字 |
\A | 匹配字符串开始 |
\Z | 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串 |
\z | 匹配字符串结束 |
\G | 匹配最后匹配完成的位置 |
\b | 匹配一个单词边界,也就是指单词和空格间的位置。例如, ’er\b’ 可以匹配"never" 中的 ’er’,但不能匹配 “verb” 中的 ’er' |
\B | 匹配非单词边界。’er\B’ 能匹配 “verb” 中的 ’er’,但不能匹配 “never” 中的 ’er' |
\n | 匹配一个换行符 |
\t | 匹配一个制表符 |
\1…\9 | 匹配第n个分组的子表达式 |
\10 | 匹配第n个分组的子表达式,如果它经匹配。否则指的是八进制字符码的表达式 |
字符相关的规则:
模式 | 描述 |
---|---|
^ | 匹配字符串的开头 |
$ | 匹配字符串的末尾 |
. | 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符 |
[…] | 用来表示一组字符,单独列出:[amk] 匹配 ‘a’,’m’或’k’ |
[^…] | 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符 |
* | 匹配0个或多个的表达式 |
+ | 匹配1个或多个的表达式 |
? | 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式 |
{n} | 精确匹配n个前面表达式 |
{n, m} | 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式 |
a|b | 匹配a或b |
( ) | 匹配括号内的表达式,也表示一个组 |
(?imx) | 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域 |
(?-imx) | 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域 |
(?: ) | 类似 (…), 但是不表示一个组 |
(?imx: ) | 在括号中使用i, m, 或 x 可选标志 |
(?-imx: ) | 在括号中不使用i, m, 或 x 可选标志 |
(?#…) | 注释 |
(?= ) | 前向肯定界定符。如果所含正则表达式,以 … 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边 |
(?! re) | 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功 |
(?> re) | 匹配的独立模式,省去回溯 |
中文 - [\u2E80-\u9FFF]
匹配模式
正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志(flags=0)。
修饰符 | 描述 |
---|---|
re.I | 使匹配对大小写不敏感 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ |
re.S | 使 . 匹配包括换行在内的所有字符 |
re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
例如很多时候匹配的内容是存在换行的问题的,这个时候就需要拥戴匹配模式re.S来匹配换行的内容 - re.match('','',re.S)
三大匹配方法
1. re.match(pattern, string, flags=0)
- pattern - 正则表达式
- string - 要匹配的字符串
- flags - 匹配模式,用于控制正则表达式的匹配方法,如是否区分大小写,多行匹配等
从头开始匹配。从字符串的起始位置匹配一个模式,如果不是起始位置匹配的话,返回None
2. re.search(pattern, string, flags=0)
- pattern - 正则表达式
- string - 要匹配的字符串
- flags - 匹配模式
search方法会扫描整个字符串,并返回第一个成功匹配的结果。使用match方法时必须匹配头部,因此不是很方便,search方法使用的较多。
3. re.findall(pattern, string, flags=0)
- pattern - 正则表达式
- string - 要匹配的字符串
- flags - 匹配模式
findall方法会搜索整个字符串,以列表的形式返回全部匹配的结果。
做一下总结:
-
匹配多个结果,使用findall()
-
匹配一个结果,使用match()/search()
从头开始匹配,使用match();从任意位置匹配,使用search()
更多方法
1. re.compile(pattern, flags=0)
compile方法将正则表达式的样式编译为一个 正则表达式对象 (正则对象),可以用于search等方法的匹配:
prog = re.compile(pattern)
result = prog.search(string)
# 等价于
result = re.search(pattern, string)
2. re.split(pattern, string, maxsplit=0, flags=0)
- pattern - 正则表达式
- string - 要匹配的字符串
- maxsplit - 最多分隔次数
- flags - 匹配模式
用 pattern 分开 string 。 如果在 pattern 中捕获到括号,那么所有的组里的文字也会包含在列表里。如果 maxsplit 非零, 最多进行 maxsplit 次分隔, 剩下的字符全部返回到列表的最后一个元素。
>>> re.split(r'\W', "Chaos isn't a pit,chaos is a ladder.")
['Chaos', 'isn', 't', 'a', 'pit', 'chaos', 'is', 'a', 'ladder', '']
>>> re.split(r'\s|,', "Chaos isn't a pit,chaos is a ladder.")
['Chaos', "isn't", 'a', 'pit', 'chaos', 'is', 'a', 'ladder.']
>>> re.split(r'\s|,', "Chaos isn't a pit,chaos is a ladder.",maxsplit=1)
['Chaos', "isn't a pit,chaos is a ladder."]
3. re.sub(pattern, repl, string, count=0, flags=0)
- pattern - 正则表达式
- repl - 新字符串
- string - 原字符串
- count - 替换次数
- flags - 匹配模式
替换字符串中每一个匹配的子串后返回替换后的字符串
>>> re.sub('\d','','12ab34cd')
'abcd'
在替换字符时,如需获取匹配的字符,可以通过\1
字符实现
>>> re.sub('(\d)',r'\1+1','龙妈一共有3条龙🐲')
'龙妈一共有3+1条龙🐲'
一些补充方法
group()
- 获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用group()
或group(0)
groups()
- 返回一个元组,包含所有匹配的子组,在样式中出现的从1到任意多的组合。span()
- 返回一个元祖,包含匹配结果的起始、终止下标start()
- 返回一个int类型的起始下标end()
- 返回一个int类型的终止下标
来写一些正则吧,强势提高生产力!
>>> re.search('\d+.{7}','2380540710@qq.comwohug').group()
'2380540710@qq.com'
>>> skip_doms = re.findall(
rf'(<url>\n\s+)(<loc>.*?/{keyword}/.*?</loc>\n\s+)(<lastmod>.*?</lastmod>\n\s+)?(</url>)', text)