python成长之路17——re
一、正则表达式
(1)数量词的贪婪模式与非贪婪模式
正则表达式通常用于在文本中查找匹配的字符串。Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字 符;非贪婪的则相反,总是尝试匹配尽可能少的字符。例如:正则表达式”ab*”如果用于查找”abbbc”,将找到”abbb”。而如果使用非贪婪的数量 词”ab*?”,将找到”a”。
注:我们一般使用非贪婪模式来提取。
(2)反斜杠问题
与大多数编程语言相 同,正则表达式里使用”\”作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符”\”,那么使用编程语言表示的正则表达式里将需要4个反 斜杠”\\\\”:前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。
Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r”\\”表示。同样,匹配一个数字的”\\d”可以写成r”\d”。有了原生字符串,妈妈也不用担心是不是漏写了反斜杠,写出来的表达式也更直观勒。
二、re
(1)re.match(正则表达式,原字符串,[参数])
1 import re 2 3 pattern = re.compile(r'hello',re.I) 4 #re.I 忽略大小写 5 res = re.match(pattern,'HelloHELLO') 6 if res: 7 print res.group() 8 9 m=re.compile(r'(\w+) (\d+) (?P<zy>\W)(?P=zy)(\d+)') 10 res = re.match(m,"hello 123 !!234") 11 if res: #匹配成功为True 12 print res.group() 13 print res.string #如果匹配成功的话,返回匹配时用到的文本 14 print res.re #匹配时使用的Pattern对象 15 print m #匹配时使用的Pattern对象 16 print res.pos #正则表达式开始搜索的索引(不是开始匹配),索引是从0开始的 17 print res.endpos #正则表达式结束搜索的索引(不是结束匹配) 18 print res.lastindex #正则表达式最后一个匹配分组"()"的编号,字符串从前往后一个"()"是一个分组, 19 # 分组是从第一个分组开始的,使用分组别名"(?P=zy)"的不算一个分组 20 # 分组别名"(?P=zy)"和分组编号"(\1)"必须匹配这个别名和编号之前匹配到的 21 # 字符串,eg:之前匹配到的是"a12",那这个别名或者编号就必须是匹配"a12" 22 print res.lastgroup #同上,这个是最后一个匹配分组"()"的别名,最后一个分组没有别名则为None 23 print res.group(1,2) #打印第一个和第二个分组 24 print res.groups() #打印所有分组 25 print res.groupdict() #如果分组有别名,会将这个分组的别名作为key,分组匹配到的字符串作为value组成个dict 26 print res.start(2) #第二个分组匹配开始的索引 27 print res.end(2) #第二个分组匹配结束的索引 28 print res.span(2) #(start,end)组成的元祖 29 print res.expand(r'\2 \3\1') #以"分组2 分组3分组1"的格式输出 30 31 执行结果: 32 hello 123 !!234 33 hello 123 !!234$#fd 34 <_sre.SRE_Pattern object at 0x106e00840> 35 <_sre.SRE_Pattern object at 0x106e00840> 36 0 37 19 38 4 39 None 40 ('hello', '123') 41 ('hello', '123', '!', '234') 42 {'zy': '!'} 43 6 44 9 45 (6, 9) 46 123 !hello
(2)re.search:
参数,属性和方法同re.match
区别是:
re.match是从string头开始匹配的,如果string头不匹配则返回None,而re.search会扫描整个string查找匹配
(3)re.split(正则表达式,原字符串,[参数]):
re.split
re.findall
将匹配到的字符串作为分隔符对字符串进行分隔,最后一个参数是最大分隔次数,如果不写,默认全部分隔
1 m = re.compile(r'\d+') 2 res = re.split(m,"one1two2ten10three3four4") 3 print res 4 res2 = re.split(m,"one1two2ten10three3four4",2) 5 print res2 6 7 执行结果: 8 ['one', 'two', 'ten', 'three', 'four', ''] 9 ['one', 'two', 'ten10three3four4’]
(4)re.findall(正则表达式,原字符串,[参数]):
以列表形式返回全部能匹配的子串
1 m = re.compile(r'(\w+) (\d+)') 2 res = re.findall(m,"@#qw 123 ! !876tw 345^") 3 print res 4 5 执行结果: 6 [('qw', '123'), ('876tw', '345’)]
(5)re.finditer(正则表达式,原字符串,[参数]):
返回一个匹配子串的迭代器
1 m = re.compile(r'(\w+) (\d+)') 2 res = re.finditer(m,"@#qw 123 ! !876tw 345^") 3 #返回一个匹配结果的迭代器 4 print res 5 for i in res: 6 print i.group() 7 8 执行结果: 9 <callable-iterator object at 0x10f1083d0> 10 qw 123 11 876tw 345
(6)re.sub(正则表达式,替换字符串,原字符串,最多替换次数):
1 m = re.compile(r'(\w+) (\w+) ') 2 s = "1qa 2ws 3ed fr4 " 3 print "原str:",s 4 res = re.sub(m,r'123 abc',s) 5 print "res:",res 6 res1 =re.sub(m,r'\2 \1',s) 7 print "res1:",res1 8 9 def func(m): 10 return "i am group1:" + m.group(1) + "\ni am group2:" + m.group(2) + "\n" 11 res = re.sub(m,func,s) 12 print res 13 14 执行结果: 15 原str: 1qa 2ws 3ed fr4 16 res: 123 abc123 abc 17 res1: 2ws 1qafr4 3ed 18 i am group1:1qa 19 i am group2:2ws 20 i am group1:3ed 21 i am group2:fr4
(7)re.subn(正则表达式,替换字符串,原字符串,最多替换次数)
用法功能同re.sub
区别是:
re.sub返回的是字符串
re.subn返回的是元祖:(替换后字符串,替换次数)
1 m = re.compile(r'(\w+) (\w+) ') 2 s = "1qa 2ws 3ed fr4 " 3 print "原str:",s 4 res = re.subn(m,r'123 abc',s) 5 print "res:",res 6 res1 =re.subn(m,r'\2 \1',s) 7 print "res1:",res1 8 9 def func(m): 10 return "i am group1:" + m.group(1) + "\ni am group2:" + m.group(2) + "\n" 11 res = re.subn(m,func,s) 12 print res 13 14 执行结果: 15 原str: 1qa 2ws 3ed fr4 16 res: ('123 abc123 abc', 2) 17 res1: ('2ws 1qafr4 3ed', 2) 18 ('i am group1:1qa\ni am group2:2ws\ni am group1:3ed\ni am group2:fr4\n', 2)