正则表达式的常见用法分为两块内容,第一部分是一般具有正则的高级语言都支持的功能,第二部分讲解Python所独特具备的正则特性。
Part 1
正则表达式是由普通字符(例如字符a到z)以及特殊字符(称为“元字符”)组成的文字模式。模式用于在搜索文本时要匹配一个或多个字符串。
(1).常见的元字符如下:
. 匹配除换行符以外的任意字符
\b 匹配单词的开始和结束
\d 匹配数字
\w 匹配字母,数字,下划线和汉字
\s 匹配任意空白符,包括空格,制表符(Tab),换行符,中文全角空格等
^ 匹配字符串的开始
$ 匹配字符串的结束
Examples:
1.匹配所有以s开头的单词 \bs\w*\b
2.匹配以s开头后跟数字的字符串(比如:s100) ^s\d*$
3.匹配网址(比如:www.google.com) www\.google\.com
(2).重复:
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或者更多次
{n,m} 重复n到m次
Examples:
1.匹配hello后面跟1个或更多数字 hello\d+
2.匹配5到12个数字的字符串 ^\d{5,12}$
3.匹配we后面跟0个或者1个数字 we\d?
(3).字符集合:
[...], 利用自定义的字符集合,可以匹配几个字符中的单个字符,以及字符范围内的单个字符。
Examples:
1.匹配a,b,c,d,e中的单个字符 [abcde]
2.匹配0到8里的数字 [0-8]
3.匹配所有的字母和数字 [0-9a-zA-Z]
(4).分支条件
正则表达式里的分支条件指的是有几种匹配规则,如果满足其中任意一种规则都应该当成匹配,具体方法是用“|”把不同的规则分隔开。
Examples:
1.匹配电话号码,一种是3位区号,8位本地号,比如:010-11223344;另一种是4位区号,7位本地号,比如:0321-1234567 0\d{2}-\d{8}|0\d{3}-\d{7}
2.匹配IP地址 ((25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.){3}((25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d))
(5).反义
有时候需要查找除某一类字符集合以外的字符,这时就需要使用反义。
常用的反义:
\W 匹配任意不是字母,数字,下划线,汉字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或结束的位置
[^a] 匹配除了a以外的任意字符
[^abcde]匹配除了a,b,c,d,e以外的任意字符
[^(123|abc)] 匹配除了1,2,3 或者a,b,c这几个字符以外的任意字符
(6).后向引用
...[比较繁琐,故先省略]
(7).零宽断言
...
(8).贪婪与懒惰
当正则表达式中包含能接受重复的限定符时,通常的行为是匹配尽可能多的字符,这就是贪婪模式。
以表达式a\w+b为例,如果搜索a12b34b,最后会匹配a12b34b,而不是a12b。如果想匹配a12b,应使用“?”来开启懒惰模式。
*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但仅可能少重复
{n,m} 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复
(9).处理选项
...
Part 2
Python与正则
对不同的语言,对正则表达式的语法绝大部分都是支持的,但是还是有略微不同,每种语言都有一些独特的匹配规则。
Python的匹配规则:
\A 仅匹配字符串开头
\Z 仅匹配字符串末尾
(?P<name>) 分组,除了原有编号外再指定一个额外的别名
(?P=name) 引用别名为<name>的分组匹配到的字符串
Python 通过re模块提供对正则表达式的支持
使用re的一般步骤是:
(1).先将正则表达式的字符串形式编译成Pattern实例;
(2).然后使用Pattern实例处理文本并获得匹配结果Match实例;
(3).最后使用Match实例获得信息。
1.re.compile(string, [flags]) #它将一个正则表达式转化为Pattern匹配对象
Example: pattern = re.compile(r'\d+')
2.re.match(pattern, string, [flags]) <等价于 pattern.match(string, [flags])>#该函数是从输入参数string(匹配的字符串)的开头开始,尝试匹配pattern,一直向后匹配,如果遇到无法匹配的字符或者已经到达string的末尾,立即返回None,反之,获得匹配的结果。
Example:
# 1.将正则表达式编译成pattern对象
pattern = re.compile(r'\d+')
# 2.使用re.match匹配文本,获得匹配结果,无法匹配时将返回None
result1 = re.match(pattern, '192abc')
if result1:
print(result1.group())
else:
print('匹配失败1')
result2 = re.match(pattern, 'abc192')
if result2:
print(result2.group())
else:
print('匹配失败2')
Result:
192
匹配失败2
3.re.search(pattern, string, [flags]) <等价于 pattern.search(string, [flags])> #search方法和match方法很类似,只是search()会扫描整个string查找匹配,而不是从string的开始位置进行匹配
Example:
# search方法的返回对象在方法和属性上和match是一致的
import re
# 将正则表达式编译成pattern对象
pattern = re.compile(r'\d+')
result1 = re.search(pattern, 'abc192edf333')
if result1:
print(result1.group())
else:
print('匹配失败1')
Result:
192
4.re.split(pattern, string, [flags]) # split 能够匹配的子串将string分割后返回列表
Example:
import re
pattern = re.compile(r'\d+')
print(re.split(pattern, 'a1b2c3d4'))
Result:
['a', 'b', 'c', 'd', '']
5.re.findall(pattern, string, [flags]) # findall 搜索整个string,以列表的形式返回能匹配的全部子串
Example:
import re
pattern = re.compile(r'\d+')
print(re.findall(pattern, 'a1b2c3d4'))
Result:
['1', '2', '3', '4']
6.re.finditer(pattern, string, [flags]) # finditer 搜索整个string,以迭代器形式返回能匹配的全部Match对象
Example:
import re
pattern = re.compile(r'\d+')
matchiter = re.finditer(pattern, 'a1b2c3d4')
for match in matchiter:
print(match.group())
Result:
1
2
3
4
7.re.sub(pattern, repl, string [,count])
Example:
import re
p = re.compile(r'(?P<word1>\w+) (?P<word2>\w+)') #使用名称引用
s = 'I say, hello, world!'
print(re.sub(p, '111', 'asd f?fdf ss!fdas ss@'))
Result:
111?111!111@
8.re.subn(pattern, repl, string [,count])
#用法和上者类似,只是返回( sub(repl, string[, count]), 替换次数 )