13.1正则表达式介绍
正则表达式顾名思义就是符合一定规则的表达式,用于匹配字符串中字符组合的模式,正则表达式使用单个字符串来描述,匹配一系列匹配某个句法规则的字符串,在很多文本编辑里,正则表达式通常被用来检索、替换那些匹配某个模式的文本(字符串)
正则表达式的设计思想就是使用一些描述性的符号和文字为字符串定义一个规则,凡是符合这个规则的,程序就认定该文本是匹配的,否则就是认定该文本是不匹配的。
13.2 正则表达式语法
13.2.1 普通字符
普通字符是正则表达式中最基本的结构之一。普通字符包括没有显示指定为元字符的所以可打印和不可打印字符,包括所有大小写、数字、标点符号等其他字符。
13.2.2字符转义
我们看到数字范围“0” 到 “9”时使用的是“【0-9】”,其中“-”表示范围并不表示“-”本身,此类字符我们称之为元字符。
如果我们想匹配“-”字符本身的话,就需要做特殊处理了
在正则表达式中,这类字符转义都有通用的方法,就是在字符前加上“\”。
例如:匹配 “[” 本身 用正则表达式可以写成 [[]
如果想匹配 “0” “-” 和“9” 三个字符,则可以写成: [0-9] 这样就会匹配到这三个字符而不是0到9十个字符。
13.2.3元字符
元字符就是在正则表达式中有特殊意义的字符以上是正则表达式中常见的元字符:
书本262页
13.2.4 限定符
限定符指输入中必须存在的字符、组或字符类的多少个实例才能找到匹配项,
上一小节中的 : “*” , “+” , “?”, “{n}” , “{n,}” , “{n,m}”都是限定符,下面介绍他们的用法:
“{n}” 限定符表示匹配上一元素n次,其中n是整数 例如:“y{5}”只能匹配“yyyyy”。“3{2}”只能匹配33 “\w{3}”可以匹配任意三个英文字母
“{n,}” 限定符表示至少,匹配上一元素n次,其中n是任意整数。例如“3{y}”可以匹配 yyy 也可以匹配 yyyyy 同理 “[0-9]{3,}” 可以匹配任意三位数及数位为3以上的数字
“{n,m}”限定符表示至少匹配上一元素n次,但不超过m次,其中n和m都是整数
“*” 限定符表示与前面的元素匹配0次或多次,相当于{0,}限定符,例如: “ 91 * 9 *” 可以匹配 919 9119 9199999等但不能匹配 9129 929等
“+” 限定符表示 匹配上一次元素一次或多次,相当于 {1,}限定符,例如“an\w+” 可以匹配 antrum 等以 an开头的三位及以上的单词 但不能匹配 “an”
“?” 限定符表示匹配上一次元素0次或一次,它相当于 “{0,1}”。例如“an?” 可以匹配 “a” 和“an”,但是不能匹配 “antrum”
13.2.5 定位符
定位符能够将正则表达式固定到行首或行尾,它们还能够创建这样的正则表达式:正则表达式将出现在一个单词内、一个单词的开头或者一个单词的结尾。
定位符用来描述字符串或单词的边界,“^”和“$” 分别指字符串的开始于结束,“\b”描述单词的前边界和后边界,“\B”表示非单词边界,以下是正则表达式的定位符。
书本264页
13.2.6 分组构造
分组构造描述了正则表达式的子表达式,用于捕获输入字符串,以下是分组构造捕获匹配的子表达式:
(子表达式)
其中“子表达式”为任何有效的正则表达式模式,使用括号的捕获按正则表达式中左括号的顺序从一开始就从左到右自带编号。
13.2.7 匹配模式
匹配模式指的是匹配的时候使用的规则,使用不同的匹配模式可能会改变正则表达式的识别,也可能会改变正则表达式中字符的匹配规定。
13.3 re模块
13.3.1 re模块介绍
正则表达式中的许多
元字符都使用反斜线“\”开头,这与Python在字符串中相同的字符使用产生冲突
有一种常见的解决方案,可以在定义字符串时在前面添加“r”前缀 例如:
print('\\\\') #输出\\
print('\\') #输出\
print(r'\\') #输出\\
print('\n')
print(r'\n')
执行结果:
\\
\
\\
\n
该前缀表示在字符串中不以任何特殊方式处理反斜线“\”
注意:r’\n’ 代表的是字符 \ 和n 而不是换行符
13.2.2 compile函数
complie函数用于编译正则表达式,生成一个Pattern对象 例如
import re
pattern = re.compile(r'\w+')
之后我们就可以使用pattern对象来进行正则匹配了
13.3.3 match函数
match方法用于查找字符串指定位置(不指定的默认匹配整个字符串)正则匹配。它只匹配一次,也就是说只要找到一个匹配的结果就返回,而不是返回所有的匹配结果。
import re
pattern = re.compile(r'\d+') #匹配至少一个数字
m1 = pattern.match('one123') #默认匹配整个字符串
print(m1) #返回None
m2 = pattern.match('one123',3,5) #匹配从位置3到5的字符
print(m2) #匹配搭配则返回Match对象
print(m2.group()) #123
m3 = re.match(r'\d+','one123') #不使用compile直接匹配,只能匹配整个字符串
print(m3)
m4 = re.match(r'[a-z]+','Abcde',re.I) #使用忽略大小写模式
print(m4)
print(m4.group()) #Abcde
执行结果如下:
None
<re.Match object; span=(3, 5), match='12'>
12
None
<re.Match object; span=(0, 5), match='Abcde'>
Abcde
13.3.4 re.search
search方法用于查找字符串指定位置(不指定的默认匹配所有)正则匹配,它只匹配一次,也就是只要找到一个匹配的结果就返回,而不会返回所有匹配的结果。
seach函数与match函数的区别:match函数需要完全满足正则表达式才返回,二search函数只需要字符串包含匹配正则表达式的子串就认为匹配。
import re
pattern = re.compile(r'\d+') #至少匹配一个数字
m1 = pattern.search('one123') #默认匹配整个字符串
print(m1) #注意这里与macth的区别
print(m1.group()) #123
m2 = pattern.search('one123',0,4) #匹配从位置0到4的字符
print(m2) #匹配到则返回Macth对象
print(m2.group()) #1
m3 = re.search(r'\d+','one123') #不使用compile直接匹配,匹配整个字符串
print(m3)
print(m3.group()) #123
m4 = re.search(r'[a-z]+','123Abcde',re.I) #使用忽略大小写模式
print(m4) #返回Macth对象
print(m4.group()) #Abcde
执行结果:
<re.Match object; span=(3, 6), match='123'>
123
<re.Match object; span=(3, 4), match='1'>
1
<re.Match object; span=(3, 6), match='123'>
123
<re.Match object; span=(3, 8), match='Abcde'>
Abcde
13.3.5 re.findall
match和search函数都是一次匹配,只要找到一个匹配结果就返回,在某些情况下,我们需要搜索整个字符串,获取全部匹配结果,这就需要findall函数。
findall函数的使用方法与match函数和search函数类似,但是返回结果却不同:无论是否匹配到 都会返回一个list对象
import re
pattern = re.compile(r'\d{2}') #匹配至少一个数字
m1 = pattern.findall('one1234') #默认匹配整个字符串
print(m1) #['12','34']
m2 = pattern.findall('one1234',0,4) #匹配从0到4的字符
print(m2) #[]
m3 = re.findall(r'\d+','one123') #不使用compile直接匹配,只能匹配整个字符串
print(m3) #['123']
m4 = re.findall(r'[a-z]','123Abcde',re.I) #使用忽略大小写模式
print(m4)
执行结果如下:
['12', '34']
[]
['123']
['A', 'b', 'c', 'd', 'e']
re.split
字符串也有split方法,但是字符串只能完全匹配相同的字符,re模块中split方法可以用正则表达式丰富分割字符串的规则。
import re
pattern = re.compile(r'[\s\,\;]+') #匹配空格和:
m1 = pattern.split('a,b;;c d')
print(m1) #['a','b','c','d']
m2 = re.split(r'[\s\,\;]+','a,b;;c d') #['a','b','c','d']
print(m2)
执行结果:
['a', 'b', 'c', 'd']
['a', 'b', 'c', 'd']
13.3.7 re.sub
同样re模块提供了使用正则表达式来替代字符串的方法 -------sub方法
import re
s = 'heelo 1 worl23d 456'
pattern = re.compile(r'(\w+)(\w+)')
m1 = pattern.sub('hello world',s) #使用hello world替换 hello 123 和world 456
print(m1) #hello world hello world
m2 = pattern.sub('hello world',s,1) #只替换一次
print(m2)
m3 = re.sub(r'(\w+)(\w+)','hello world',s,1)
print(m3)
执行结果如下:
hello world hello world hello world hello world
hello world 123 world 456
hello world 123 world 456