Python:正则表达式
正则表达式
一、简介:
正则表达式:是一种小型的、高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现,需要在文件最开始的地方用import re来引入。正则表达式模式被编译成一系列的字节码,然后由用C编写的匹配引擎-执行。
二、字符匹配(普通字符,元字符):
普通字符:大多数字符和字母都会和自身匹配
>>> re.findall('alex','yuanaleSxalexwupeiqi')
['alex']
元字符:
. ^ $ * + ? { } [ ] | ( ) \
示例:
>>> re.findall(r"a(\d+)b","a23b") ['23'] >>> re.findall(r"a(\d+?)b","a23b") ['23']
[ ]:
元字符[]表示字符类,在一个字符类中,只有字符^、-、]和\有特殊含义。
字符\仍然表示转义,字符-可以定义字符范围,字符^放在前面,表示非,取反。
>>> re.findall(r"a[bc]d","wwwwabcd") [] >>> re.findall(r"a[bcd]e","wwwwabcde") [] >>> re.findall(r"a[bcd]e","wwwwade") ['ade'] >>> re.findall(r"a[bc]d","wwwwabd") ['abd'] >>>
>>> re.findall(r"a[.]d","wwwwabd") [] >>> re.findall(r"a[.]d","wwwwa.d") ['a.d']
>>> re.findall(r"[a-z]","wwwwa.d") ['w', 'w', 'w', 'w', 'a', 'd'] >>> re.findall(r"[1-9]","ww3ww8a.d") ['3', '8']
| :或
注:(?:a|b)使用方法
ret = re.findall('www.(baidu|laonanhai).com','sdad www.baidu.com') print(ret) #打印结果:['baidu'] ret = re.findall('www.(baidu|laonanhai).com','sdad www.laonanhai.com') print(ret) #打印结果:['laonanhai'] ret = re.findall('www.(?:baidu|laonanhai).com','sdad www.laonanhai.com') print(ret) #打印结果:['www.laonanhai.com']
[^]:取反
>>> re.findall(r"[^1-9]","ww3ww8a.d") ['w', 'w', 'w', 'w', 'a', '.', 'd'] >>> re.findall(r"[^1-9]","ww3ww8a.d0") ['w', 'w', 'w', 'w', 'a', '.', 'd', '0']
特殊符号:
”^“ “ $ ”分别指出一个字符串的开始和结束。
示例:
“^The”:表示以“The”开始的字符串
“ok$”:表示以“ok”结束的字符串
\d 匹配任何十进制数;它相当于类 [0-9]。
\D 匹配任何非数字字符;它相当于类 [^0-9]。
\s 匹配任何空白字符;它相当于类 [ \t\n\r\f\v]。
\S 匹配任何非空白字符;它相当于类 [^ \t\n\r\f\v]。
\w 匹配任何字母数字字符;它相当于类 [a-zA-Z0-9_]。
\W 匹配任何非字母数字字符;它相当于类 [^a-zA-Z0-9_]
\b: 匹配一个单词边界,也就是指单词和空格间的位置。
\b只是匹配字符串开头结尾及空格回车等的位置, 不会匹配空格符本身
示例:
\s,\w,\d:
>>> re.findall(r"\s","ww3w w8a.d0") [' '] >>> re.findall(r"\w","ww3ww8a.d0") ['w', 'w', '3', 'w', 'w', '8', 'a', 'd', '0'] >>> re.findall(r"\d","ww3ww8a.d0") ['3', '8', '0']
\b:
>>> re.findall(r"\babc\b","abcsdsadasabcasdsadasdabcasdsa")
[]
>>> re.findall(r"\babc","abc sdsadasabcasdsadasdabcasdsa")
['abc']
>>> re.findall(r"\babc\b"," abc sdsadasabcasdsadasdabcasdsa")
['abc']
\:
反斜杠后边跟元字符去除特殊功能,
反斜杠后边跟普通字符实现特殊功能。
引用序号对应的字组所匹配的字符串。
>>> re.search(r"(alex)(eric)com\2","alexericcomeric").group() 'alexericcomeric'
三、函数:
匹配开头
match:re.match(pattern, string, flags=0)
>>> re.match('com', 'comwww.runcomoob').group() 'com' >>> re.match('com', 'Comwww.runComoob',re.I).group() 'Com'
re.I 使匹配对大小写不敏感
re.L 做本地化识别(locale-aware)匹配
re.M 多行匹配,影响 ^ 和 $
re.S 使 . 匹配包括换行在内的所有字符
分组:
#无分组: origin = "hello alex bcd alex lge alex acd 19" r = re.match("h\w+",origin) print(r.group()) #打印结果:hello #有分组:是将group中的值再匹配括号中的(从左到右,从外到里),有几个括号就取几个 origin = "hello alex bcd alex lge alex acd 19" r = re.match("(h)(\w+)",origin) print(r.groups()) #打印结果:('h', 'ello') #?P<>设置groupdict中的key origin = "hello alex bcd alex lge alex acd 19" r = re.match("(?P<k1>h)(?P<k2>\w+)",origin) print(r.groupdict()) #打印结果:{'k1': 'h', 'k2': 'ello'}
匹配第一个
search(search有无分组情况和match一样):re.search(pattern, string, flags=0)
>>> re.search('\dcom', 'www.4comrunoob.5com').group() '4com'
注意:
re.match('com', 'comwww.runcomoob')
re.search('\dcom', 'www.4comrunoob.5com')
一旦匹配成功,就是一个match object 对象,而match object 对象拥有以下方法:
group() 返回被 RE 匹配的字符串
start() 返回匹配开始的位置
end() 返回匹配结束的位置
span() 返回一个元组包含匹配 (开始,结束) 的位置
group() 返回re整体匹配的字符串,可以一次输入多个组号,对应组号匹配的字符串。
1. group()返回re整体匹配的字符串,
2. group (n,m) 返回组号为n,m所匹配的字符串,如果组号不存在,则返回indexError异常
3.groups() 方法返回一个包含正则表达式中所有小组字符串的元组,从 1 到所含的小组号,通常groups()不需要参数,返回一个元组,元组中的元就是正则表达式中定义的组。
>>> a = "123abc456"
>>> re.search("([0-9]*)([a-z]*)([0-9]*)",a).groups() ('123', 'abc', '456')
group(0) 列出所有括号匹配部分,group(1) 列出第一个括号匹配部分,group(2) 列出第二个括号匹配部分,group(3)列出第三个括号匹配部分。
import re >>> a = "123abc456" >>> re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0) '123abc456' >>> re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(1) '123' >>> re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(2) 'abc' >>> re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(3) '456'
获取字符串中所有匹配项
findall:可以获取字符串中所有匹配的字符串,以列表形式返回所有匹配的字符串。
findall在有组的情况下,只匹配组里的情况,以列表形式返回。如果两个组分别匹配到组里的情况,就将作为一个元祖返回给列表。
import re print(re.findall(r"a(\d+)b","a23b")) #打印结果:['23'] print(re.search(r"a(\d+)b", "a23b").group()) #打印结果:a23b
>>> p = re.compile(r'\d+') >>> print p.findall('one1two2three3four4') ['1', '2', '3', '4']
>>> re.findall(r'\d+','one1two2three3four4') ['1', '2', '3', '4']
有无分组情况:
origin = "hello alex alex bcd abcd lge acd 19" r = re.findall("a\w+",origin) r1 = re.findall("(a\w+)",origin) r2 = re.findall("(a)(\w+)",origin) print(r) print(r1) print(r2) #打印结果: ['alex', 'alex', 'abcd', 'acd'] ['alex', 'alex', 'abcd', 'acd'] [('a', 'lex'), ('a', 'lex'), ('a', 'bcd'), ('a', 'cd')] origin = "hello ax lex bed alex lge alex acd 19" n = re.findall("(a)(\w)*" , origin) print(n) #打印结果:[('a', 'x'), ('a', 'x'), ('a', 'x'), ('a', 'd')]
*:0-多次,默认情况是贪婪的。有分组,取多次,默认取最后一个值,如果后面没有符合项,会匹配空
a = "alex" n = re.findall("(\w)(\w)(\w)(\w)",a) print(n) n1 = re.findall("(\w)",a) print(n1) n2 = re.findall("(\w)*",a) print(n2) #打印结果: [('a', 'l', 'e', 'x')] ['a', 'l', 'e', 'x'] ['x', ''] n = re.findall("(\dasd)","lasd2asdp3asd98kif") print(n) #打印结果:['2asd', '3asd'] n = re.findall("(\dasd)*","lasd2asdp3asd98kif") print(n) #打印结果:['', '', '', '', '2asd', '', '3asd', '', '', '', '', '', '']
空格匹配:如果没有匹配到空格,将返回空内容,并且会返回自身
#1、匹配到符合项之后再从符合项之后开始匹配 n = re.findall("\d+\w\d+","a2b3c4d5") print(n) #打印结果:['2b3', '4d5'] #2、空格匹配(字符串中有八个字符,返回了九个空格) n = re.findall("","a2b3c4d5") print(n) #打印结果:['', '', '', '', '', '', '', '', '']
re.compile(strPattern[, flag]):
>>> text = "JGood is a handsome boy, he is cool, clever, and so on..." >>> regex = re.compile(r'\w*oo\w*') >>> print regex.findall(text) ['JGood', 'cool']
sub :替换
re.sub(pattern, repl, string, max=0)
>>> re.sub("g.t","have",'I get A, I got B ,I gut C') 'I have A, I have B ,I have C' >>> re.sub("g.t","have",'I get A, I got B ,I gut C',2) 'I have A, I have B ,I gut C'
subn:返回替换次数
>>> re.subn("g.t","have",'I get A, I got B ,I gut C') ('I have A, I have B ,I have C', 3)
split:分割
>>> p = re.compile(r'\d+') >>> p.split('one1two2three3four4') ['one', 'two', 'three', 'four', ''] >>> re.split('\d+','one1two2three3four4five') ['one', 'two', 'three', 'four', 'five']
有无分组情况:
#无分组: origin = "hello alex bcd abcd lge acd 19" n = re.split("a\w+",origin) print(n) #打印结果:['hello ', ' bcd ', ' lge ', ' 19'] #有分组: n = re.split("a(\w+)",origin) print(n) #打印结果:['hello ', 'lex', ' bcd ', 'bcd', ' lge ', 'cd', ' 19'] #添加参数2:2是最大分割次数 n = re.split("a(\w+)",origin,2) print(n) #打印结果:['hello ', 'lex', ' bcd ', 'bcd', ' lge acd 19']
finditer:finditer(string[, pos[, endpos]]) | re.finditer(pattern, string[, flags]):
搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。
>>> p = re.compile(r'\d+') >>> iterator = p.finditer('12 drumm44ers drumming, 11 ... 10 ...') >>> for match in iterator: ... match.group() , match.span() ... ('12', (0, 2)) ('44', (8, 10)) ('11', (24, 26)) ('10', (31, 33))
w = re.finditer(r'\d+','12drumm44ers drumming, 11...10...') for aa in w: print(aa.group()) #打印结果: 12 44 11 10
练习:计算器计算:
1 - 2 * ( (60 - 30 + (-40.0/5) * (9 - 2 * 5/3 + 7 / 3 * 10/4*2 +10 *5/14)) -(-4*3)/(16-3*2))
1 import re 2 3 4 def add_op(arg): # 定义加法函数 5 arg = arg.replace("++", "+").replace("--", "+").replace("+-", "-").replace("-+", "-") # 替换符号 6 num = re.findall("([+\-]?\d+\.?\d*)", arg) #匹配所有数字 7 result = 0 8 for i in num: #循环数字列表进行累加 9 result = result + float(i) 10 return result 11 12 def mul(arg): #定义乘除函数 13 while True: 14 result = re.split("(\d+\.?\d*[\*/][\+-]?\d+\.?\d*)",arg,1) #匹配乘法或除法 15 if len(result) == 3: 16 bef,cen,aft = result 17 if "*" in cen: #判断乘号是否在cen里面 18 num1,num2 = cen.split("*") #将乘号进行分割得到乘数 19 new_cen = float(num1) * float(num2) #将乘数相乘得到乘积 20 arg = bef +str(new_cen) + aft #将乘积放入新的字符串表达式 21 elif "/" in cen: #判断除号是否在cen里面 22 num1,num2 = cen.split("/") #分割除号得到除数和被除数 23 new_cen = float(num1) / float(num2) #进行除法运算 24 arg = bef + str(new_cen) + aft #将商放入新的字符串表达式 25 else: 26 return add_op(arg) 27 28 def calc(arg): 29 while True: 30 arg = arg.replace(" ","") 31 result = re.split("\(([^()]+)\)",arg,1) #匹配最里面的括号并且只取括号中的内容 32 if len(result) == 3: 33 bef,cen,aft = result 34 # 计算括号中的表达式,先乘除后加减,得到计算结果 35 r = mul(cen) 36 #使用计算结果组成新的字符串表达式 37 arg = bef + str(r) + aft 38 else: #计算完括号后开始按照先乘除再加减的运算 39 return mul(arg) 40 41 origin = "1 - 2 * ( (60 - 30 + (-40.0/5) * (9 - 2 * 5/3 + 7 / 3 * 10/4*2 +10 *5/14)) -(-4*3)/(16-3*2))" 42 r = calc(origin) 43 print(r) 44 print(eval(origin))