正则表达式, 是一门独立的搜索和匹配字符串的语言,只不过在各种编程语言中得到了实现,其中perl语言的正则表达式堪称是范本,很多其他编程语言都参考perl的正则语法来实现。python中的正则表达式通过内置模块re来实现,与perl的正则表达式操作类似,如果你熟悉perl语言的话,对于python的正则也可以轻松上手。
基本用法如下
>>> a = re.search(r'c','abc123')>>> a
<re.Match object; span=(2, 3), match='c'>
其中r前缀指定的字符串称之为正则表达式的pattern, 后面是需要待匹配的字符串,正则的搜索引擎会从字符串的开头进行查找,来找出符合条件的字符, 上述例子从字符串abc123的开头进行查找,查找特定的字符c。
对于正则表达式,有以下几个基础概念
1. 字符集
正则的基本作用是匹配字符串,在开头的例子中用指定字符来进行匹配,这样无疑更加精确,但是缺少灵活性,比如匹配以下两个字符中的数字
abc123
abc456
如果用指定数字的方式来匹配,上述两个字符的匹配就要写成两种
re.search(r’123’,’abc123’)
re.search(r’456’,’abc456’)
这样显然太局限了,为了更加通用,提出了字符集的概念,事先定义了几种匹配常用字符的字符集
- \d , 匹配一个0到9之间的数字
- \w, 匹配数字,字母,下划线中的任意一个字符
- \s, 匹配任意一个空白字符,即\r\b\n\t\f中的任意一个,
- \D , 匹配任意一个非数字的字符
- \W, 匹配任意一个非数字,字母,下划线中的字符
- `\S, 匹配任意一个非空白字符
- ., 点号,默认匹配任意一个非换行符的字符
对应的字符大写之后,可以看做相反的集合。另外,也支持通过方括号来自定义字符集合,用法如下
# 相当于\d[0-9]
# 相当于\w
[A-Za-z0-9_]
# 相当于\s
[\r\n\t\f]
用字符集再来匹配上述例子,写法如下
re.search(r’\d\d\d’,’abc123’)
re.search(r’\d\d\d’,’abc456’)
这样用同一个正则就可以了。
2. 量词
从基本用法也可以看出,默认情况下,一个字符集只匹配一个字符,为了匹配变长的情况,比如匹配以下两个字符串中的数字
abc123
abc1234
在正则的pattern后面可以添加量词,控制正则匹配的次数,常用的量词如下
用量词,上述匹配写法如下
re.search(r’\d+’,’abc123’)
re.search(r’\d+’,’abc1234’)
用了量词之后,更加通用。默认情况下,量词为贪婪匹配,即匹配最长的符合模式的字符,看下面的例子
>>> re.search(r'[\w;]+;','abc;123;123')<re.Match object; span=(0, 8), match='abc;123;'>
用了加号的情况下,匹配到了第二个分号,此时如果只需要匹配到第一个分号,我们可以在量词的后面添加?, 使其变为非贪婪匹配,写法如下
>>> re.search(r'[\w;]+?;','abc;123;123')<re.Match object; span=(0, 4), match='abc;'>
可以看到,在非贪婪匹配中,遇到第一个符合模式的字符,程序就停止了,不会继续往后查找,而默认的贪婪模式会接着往下检索。
3. 位置限定符
默认情况下,正则从字符串开头进行检索,寻找任意位置符合模式的字符。但有时我们需要匹配字符的位置进行限定,比如匹配以下字符串末尾的数字
123abc123
此时,我们就需要用到位置限定符号,也叫做锚定符,常用的如下
用锚定符,上述匹配的写法如下
re.search(r’\d+$’,’123abc123’)
4. 模式修饰符
修饰符影响正则的匹配行为,常用的修饰符如下
修饰符的用法示意如下
re.search(r’ABC’,’123abc’, re.I)
除了上述写法,也支持以下写法
re.search(r’(?i)ABC’,’123abc’)
re.search(r’(?i:ABC)’,’123abc’)
在圆括号中的问号后面添加修饰符,i对应re.I。正则表达式在实际开发中常见用途如下
1. 条件判断
查看字符串是否匹配特定模式, 常用作逻辑判断语句,用法如下
if re.search(r'\d+','abc123'):print("success")
else:
print("failed")
2. 提取符合模式的字符串
通过在模式的两端添加圆括号,可以捕获对应的字符,用法如下
# 在正则中使用圆括号进行捕获>>> re.search(r'(abc)(123)','abc123')
<re.Match object; span=(0, 6), match='abc123'>
# groups函数返回捕获元素的元组
>>> re.search(r'(abc)(123)','abc123').groups()
('abc', '123')
# group函数默认值为0
>>> re.search(r'(abc)(123)','abc123').group()
'abc123'
# 下标0返回原始待匹配字符串
>>> re.search(r'(abc)(123)','abc123').group(0)
'abc123'
# 下标1返回第一个捕获的字符串
>>> re.search(r'(abc)(123)','abc123').group(1)
'abc'“”
# 下标2返回第二个捕获的字符串
>>> re.search(r'(abc)(123)','abc123').group(2)
'123'
3, 替换特定字符串
通过re.sub函数来特换特定字符串,用法如下
>>> re.sub(r'abc', 'ABC', 'abc123abc')'ABC123ABC'
>>> re.sub(r'abc', 'ABC', 'abc123abc', count = 1)
'ABC123abc'
返回值为替换后的字符串,count参数控制替换的次数,默认值为0,表示全部替换。除此之外,还有一个re.subn函数,返回值为替换后的字符串和替换次数构成的元组,用法如下
>>> re.subn(r'abc', 'ABC', 'abc123abc')('ABC123ABC', 2)
3. 灵活的分隔字符串
字符串自带的split方法只允许以固定字符分隔字符串,用re.split函数,可以用正则来分隔字符串,更加灵活,用法如下
>>> re.split(r'[:=]', 'A=B:C')['A', 'B', 'C']
4. 查找特定字符串
通过re.findall函数,查找所有符合模式的字符串,用法如下
>>> re.findall(r'\d+', '123abc123abc123')['123', '123', '123']
返回值为一个列表,与之对应的还有一个re.finditer函数,返回值为迭代器,用法如下
>>> number = re.finditer(r'\d+', '123abc123abc123')>>> for i in number:
... print(i.group())
...
123
123
123
除了常用的re.search函数外,还有一个re.match函数,该函数只支持从字符串开头进行匹配,示意如下
# 数字不在开头,没有结果>>> re.match(r'\d+', 'abc123')
# 在开头有数字,给出匹配结果
>>> re.match(r'\d+', '123abc')
<re.Match object; span=(0, 3), match='123'>
# search更加灵活
>>> re.search(r'\d+', 'abc123')
<re.Match object; span=(3, 6), match='123'>
可以看出,相比search, match自动在正则的开始添加^锚定符号,其他行为二者是一样的。
·end·
—如果喜欢,快分享给你的朋友们吧—
关注我们,解锁更多精彩内容!