正则表达式及Python中的应用

语法

https://regexone.com/

单个字符

符号 意义
. 任意字符
\w 任意字母数字字符
\W 任意非字母数字字符
\d 任意数字
\D 任意非数字
\s 任意空白:空格、换行符、制表符、回车
\S 任意非空白
\b 词和非词的边界
[abc] abc中任意一个字符
[^abc] 除了abc以外的一个字符
[a-z] a-z中任意一个字符
[^a-z] 除了a-z的任意一个字符

重复模式

符号 意义
{5} 之前一个匹配模式重复5次
{1,5} 之前一个匹配模式重复1-5次
* 重复0次或更多次
+ 重复1次或更多次
? 重复0次或1次

位置匹配

符号 意义
^ 行首
$ 行尾

分组提取

符号 意义
(…) 提取括号中内容
(…(…)…) 嵌套括号,以括号出现的先后顺序分别提取内容
(abc|def) 匹配abc或def

分组还可以不提取,用来判别复杂的模式,如(…)?判别某模式出现与否

反向引用

符号 意义
\0 匹配到的全文
\1 匹配到的第一组
\2 匹配到的第二组

\1 \2 可以用在文本编辑器匹配并替换中,(\d+)-(\d+) 替换为 \2-\1

注:在vscode中,搜索中用\1 \2,替换中用$1 $2

常用表达

表达式 意义
^-?\d+(,\d+)*(.\d+(e\d+)?)?$ 匹配各种类型的数字,包含负号、小数、科学计数、分隔符
(\w+).(gif|jpg|png)$ 匹配所有图片类型,提取文件名和扩展名
^\s*(.*)\s*$ 去除行首行尾多余的空白,提取有信息的内容
[\w\.]+ 匹配文件名,包含数字字母和.
(\w+)://([\w-.]+)(:(\d+))?/ 提取url中的协议、域名、端口

Python 中的应用

https://regexone.com/references/python

查找首次出现的匹配

1
2
3
import re

matchObject = re.search(pattern, input_str, flags=0)

matchObject为特殊数据结构,需要调用方法提取出匹配的文本

返回匹配的整体

1
matchObject.group(0)

返回匹配的 capture group

1
2
matchObject.group(1)
matchObject.group(2)

返回匹配的整体在原字符串中的位置

1
2
matchObject.start()
matchObject.end()

re.findall

查找全部出现的匹配,返回列表

如果无 capture group,返回匹配整体的列表

1
2
3
4
regex = r"[a-zA-Z]+ \d+"
matches = re.findall(regex, "June 24, August 9, Dec 12")

# matches = ['June 24', 'August 9', 'Dec 12']

如果有 capture group,返回每个匹配提取出的 capture group 的元组组成的列表

1
2
3
4
regex = r"([a-zA-Z]+) (\d+)"
matches = re.findall(regex, "June 24, August 9, Dec 12")

# matches = [('June', '24'), ('August', '9'), ('Dec', '12')]

re.finditer

查找全部出现的匹配,返回由 matchObject 构成的迭代器,可以迭代调用 matchObject 的方法

1
2
3
4
5
6
7
8
9
regex = r"([a-zA-Z]+) (\d+)"
matches = re.finditer(regex, "June 24, August 9, Dec 12")
for match in matches:
print(match)

# output:
# <re.Match object; span=(0, 7), match='June 24'>
# <re.Match object; span=(9, 17), match='August 9'>
# <re.Match object; span=(19, 25), match='Dec 12'>

re.sub

搜索并替换,返回替换后的全文,count明确做几次替换,忽略则默认替换所有

1
replacedString = re.sub(pattern, replacement_pattern, input_str, count)

可以用到反向引用

1
2
3
4
regex = r"([a-zA-Z]+) (\d+)"
re.sub(regex, r'\2 of \1', "June 24, August 9, Dec 12")
# output:
# '24 of June, 9 of August, 12 of Dec'

re Flags

re 模块中每一种匹配方法基本上都有 flags 参数,默认为0.

Flag 意义
re.IGNORECASE 不区分大小写
re.MULTILINE 使^和$将\n分开的各行作为行,否则默认是全文
re.DOTALL 使.能够匹配\n

re.RegexObject

需要多次重用相同的pattern匹配时,可以将pattern提前编译,提高运算速度

1
regexObject = re.compile(pattern, flags=0)

regexObject 拥有的方法与之前re的函数基本相同

1
2
3
4
5
regex = re.compile(r'(\w+) World')

result = regex.search('Hello World is the easiest')
results = regex.findall('Hello World, Bonjour World')
replacedString = regex.sub(r'\1 Earth', 'Hello World')