re 正则匹配模块
一、元字符:
. 通配符,匹配任意一个字符( 除外) ^ 开头 $ 结尾 * 重复匹配,重复前面的字符0个或多个; 特殊情况: import re ret = re.findall('7*','efe') print(ret) # 输出['', '', '', ''] 因为*可以为0个或多个。后面字符串中,每个字符前后都有0个7; + 重复匹配,重复前面的字符1个或多个; ? 重复匹配,重复前面的字符0个或一个字符 {} 重复匹配,重复前面的字符指定的次数 例如: import re ret = re.findall('a{3}b','aaaab') print(ret) # 输出 ['aaab'] 重复3次a;这里也可以匹配范围,如 a{1,3} 即重复1到3次;{1,}表示1到无穷次; [] 字符集;表示范围,或的关系;同时,取消元字符的特殊意义,将元字符变为普通字符(有三个例外 ^ -);[]中的^是取反的意思;反斜杠后面跟普通字符来实现特殊功能的字符可以使用在[]里,例如 [d] 表示0-9的数字; 例如: a[cde]h 表示 ach或adh或aeh [a-z] 表示小写字母a到z [0-9a-zA-Z] 表示数字、大小写字母 [^456] 表示非4,非5 和 非6;即所有的项都取反 | 管道符,表示或者; 反斜杠; 反斜杠后面跟元字符,去除元字符的特殊功能;即转义; 例如: import re ret1 = re.findall('*','hello*ok') #* 来表示 *号本身,而不是通配符; ret2 = re.findall('\\','hellook') #\\ 表示 ;在python解释器中解释时,反斜杠需要转义,传给re模块后,re模块中的正则也需要转义;故这里的\\给正则时相当于 \; ret3 = re.findall(r'\','hellook') # 行显示,表示后面字符串没有特殊意义;和上面\\效果一样; 反斜杠后面跟普通字符,实现特殊功能; 如下: d 匹配任何十进制数;相当于 [0-9] D 匹配任何非数字字符;相当于[^0-9] s 匹配任何空白字符;相当于 [ fv]; 前面是空格 S 匹配任何非空白字符;相当于 [^ fv]; 前面是空格 w 匹配任何字母数字字符;相当于 [a-zA-Z0-9_] W 匹配任何非字母数字字符;相当于 [^a-zA-Z0-9_] 匹配一个单词边界,也就是指单词和空格间的位置 例如: import re ret = re.findall(r'I','Hello,I am a LIST.') print(ret) # 输出 I am 这个 I;会检测单词的边界;即字母的边界如果是特殊字符,则认为该字母是一个单词;但是有例外,如这里假如一个单词,结尾是I,则也会匹配到。 () 分组;注意分组在findall方法中的使用,见findall方法处; 例如: import re ret = re.findall('(as)+','sfefeffeasasas') print(ret) # 输出 ['as'] ret1 = re.search('(as)+','sfefeffeasasas').group() print(ret1) # 输出 asasas
二、 正则表达式re模块常用方法
1. findall()
所有匹配的结果都返回到一个列表中;findall中使用分组时,只返回分组所匹配的内容;当分组外面使用+等符号时,只打印最后一次匹配到的(如下面的ret1、ret2);
分组的优先级高于普通的匹配,如果想都匹配,可以使用?:来改变优先级;
例如:
import re
ret1 = re.findall('www.(w)+.com','www.bashrunning.com')
ret2 = re.findall('www.(w)(w)+.com','www.bashrunning.com')
ret3 = re.findall('www.(w+).com','www.bashrunning.com')
ret4 = re.findall('www.(w)(w+).com','www.bashrunning.com')
ret5 = re.search('www.(w)+.com','www.bashrunning.com').group()
ret6 = re.findall('www.(?:w+).com','www.bashrunning.com')
print(ret1) # 输出 ['g']
print(ret2) # 输出 [('b','g')]
print(ret3) # 输出 ['bashrunning']
print(ret4) # 输出 [('b','ashrunning')]
print(ret5) # 输出 www.bashrunning.com
print(ret6) # 输出 www.bashrunning.com 使用?:时,可以将分组的优先级降低;这样,就可以返回所有匹配的内容;
2. search()
返回一个对象(object);对象有group方法来取匹配结果;如果没有匹配到,则返回None;
从左开始匹配,只返回匹配到的第一个对象;
3. match()
返回一个对象(object);只在字符串开头匹配,也是从左开始匹配,只匹配第一个对象;如果没有匹配到,则返回None;
match方法可以看做特殊的search方法;即 re.match('a','abcd') 等效于 re.search('^a','abcd');
4. split()
分割字符串,返回一个列表;假如分隔符在字符串的边界,则返回的列表中会有一个空
例如:
import re
ret1 = re.split('f','egefabc')
print(ret1) # 输出 ['ege','abc']
ret2 = re.split('[fb]','egefabc')
print(ret2) # 输出 ['ege','a','c']
ret3 = re.split('[ea]','egefabc')
print(ret3) # 输出 ['','g','f','bc']
5. sub()
替换匹配的的字符为指定的字符;从左开始匹配,默认替换所有匹配到的;如果替换指定次数,加一个参数指定次数即可;
例如:
import re
ret = re.sub('ba.*ing','baidu','www.bashrunning.com')
print(ret) # 输出 www.baidu.com 即,将 匹配到的替换为 指定的字符;中间的字符串(baidu)中的特殊字符也都是原生字符;
ret2 = re.sub('abc','baidu','www.abc.com/www.abc.com',1)
print(ret2) # 输出 www.baidu.com/www.abc.com 指定了只替换一次;
其实还有一个方法,subn(),可以返回替换的次数;
例如:
import re
ret = re.subn('ba.*ing','baidu','www.bashrunning.com')
print(ret) # 输出 ('www.baidu.com',1)
6. compile()
将指定的匹配规则编译为 一个正则表达式对象;类似定义了一个函数;
例如:
import re
re_object = re.compile('bash')
ret1 = re_object.findall('bashrunning.com') # 匹配bash
ret2 = re_object.findall('bash for linux') # 匹配bash
7. finditer()
findall返回一个列表;finditer返回一个迭代器;
例如:
import re
ret = re.finditer('d','wjz123wjk456')
print(ret) # 输出 <callable_iterator object at 0x000002491C4B24A8>
g1=next(ret)
print(g1) # 输出 <_sre.SRE_Match object; span=(3, 4), match='1'>
print(g1.group()) # 输出 1
三. 其他
1. 分组
例如:
import re
ret = re.search('(?P<name>.*)/(?P<date>.*)', 'wjz/20180201')
print(ret.group()) # 返回 wjz/20180201
print(ret.group('name')) # 返回 wjz
print(ret.groupdict()) # 返回 {'name': 'wjz', 'date': '20180201'}
2. 贪婪匹配 和 惰性匹配
正则中,元字符 * + ? 都是贪婪匹配。就是尽可能多的给你匹配处理;
如果在元字符后面加上?,则会变为惰性匹配,即尽可能少的匹配;
例如:
import re
ret1 = re.search('ab*','abbbbbb')
print(ret1.group()) # 返回 abbbbbb
ret2 = re.search('ab*?','abbbbbb')
print(ret2.group()) # 返回 a
3. search、match等返回的对象的方法
获取对象:
import re
object = re.search('ab*','abbbbbb') # 得到对象object
接下来,我们看看这个对象object都有哪些方法。
对象的数据描述符:
-
endpos
返回object.group()的长度;汉字、数字、字母、特殊字符都算一个长度;
-
lastgroup
返回最后组名;如果最后一组没有定义组名,则返回None;匹配规则使用()分组;
-
lastindex
返回分组的个数;
-
pos
再补充这个;
-
re
返回对象匹配的规则;
-
regs
返回一个元组;元组中分别是 object.group()第一个字符到最后一个字符的位置、第一组的位置、第二组的位置... 例如:
import re ret = re.search('(?P<name>.*)/(?P<date>.*)/.*', 'wjz/20180201/4') print(ret.regs) # 返回 ((0, 14), (0, 3), (4, 12)) 注意,位置元组是顾头不顾尾;
-
string
返回object配置时的原始字符串; 例如:
import re ret = re.search('(?P<name>.*)/(?P<date>.*)/.{2}', 'wjz/20180201/44444') print(ret.group()) # 返回 wjz/20180201/44 print(ret.string) # 返回 wjz/20180201/44444
对象的类方法:
-
group(...)
返回匹配到的所有字符; 例如:
import re ret = re.search('(?P.{3})/(?P.*)/.{3}', 'kkkkwjz/20180201/44444') print(ret.group()) # 返回 wjz/20180201/444
-
groupdict(self, /, default=None)
返回一个字典;字典的key为组名;键值是改组匹配到的字符; 例如:
import re ret = re.search('(?P.{3})/(?P.*)/.{3}', 'kkkkwjz/20180201/44444') print(ret.groupdict()) # 返回 {'name': 'wjz', 'date': '20180201'}
-
groups(self, /, default=None)
以元组形式返回分组匹配到的内容; 例如:
import re ret = re.search('(?P.{3})/(?P.*)/.{3}', 'kkkkwjz/20180201/44444') print(ret.groups()) # 返回 ('wjz', '20180201') 即分组匹配到的字符
-
span(self, group=0, /)
返回一个元组,匹配到的字符串的在原始字符串中的起始结束位置;位置从0开始,顾首不顾尾; 例如:
import re ret = re.search('(?P.{3})/(?P.*)/.{3}', 'kkkkwjz/20180201/44444') print(ret.group()) # 返回 wjz/20180201/444 print(ret.span() # 返回 (4,20) 即 w为'kkkkwjz/20180201/44444'的第四个位置,第三个4位于第19个位置;
-
start(self, group=0, /)
返回一个数字,该数字是匹配到的字符串的最后一个字符在原字符串的位置;这里的end起始是span方法中的start位置; 例如:
import re ret = re.search('(?P.{3})/(?P.*)/.{3}', 'kkkkwjz/20180201/44444') print(ret.group()) # 返回 wjz/20180201/444 print(ret.span()) # 返回 (4,20) print(ret.start()) # 返回数字 4 即w在'kkkkwjz/20180201/44444'是第4个位置处;
-
end(self, group=0, /)
返回一个数字,该数字是匹配到的字符串的最后一个字符在原字符串的位置+1;这里的end起始是span方法中的end位置; 例如:
import re ret = re.search('(?P.{3})/(?P.*)/.{3}', 'kkkkwjz/20180201/44444') print(ret.group()) # 返回 wjz/20180201/444 print(ret.span()) # 返回 (4,20) print(ret.end()) # 返回数字 20 即第三个4 在'kkkkwjz/20180201/44444'是第19个位置处;
-
expand(self, /, template)
这个可以用sub方法替代;字符替换的;具体用法再补充;
四. 正则修饰符
正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:
修饰符 | 描述 |
---|---|
re.I(注:大写的i) | 使匹配对大小写不敏感 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ |
re.S | 使 . 匹配包括换行在内的所有字符 |
re.U | 根据Unicode字符集解析字符。这个标志影响 w, W, , B. |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
案例
-
re.I
pattern='aB' print(bool(re.match(pattern,'ab',flags=re.I)))#结果为True,若不加re.I则为False
-
re.M
re.M 即 re.MULTILINE 影响'^'和'$'的行为,指定了以后,'^'会增加匹配每行的开始(也就是换行符后的位置); '$'会增加匹配每行的结束(也就是换行符前的位置)。
pattern='^a{2}bb$' print(bool(re.match(pattern,'aabb aabb',re.M))) #加上re.M结果为True,否则为False
-
re.S
pattern='w+|.' print(bool(re.match(pattern,' ghhgb',re.S))) #加上re.S为True,否则为False