常用正则表达式符号
.' 默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行 '^' 匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE) '$' 匹配字符结尾,或e.search("foo$","bfoo\nsdfsf",flags=re.MULTILINE).group()也可以 '*' 匹配*号前的字符0次或多次,re.findall("ab*","cabb3abcbbac") 结果为['abb', 'ab', 'a'] '+' 匹配前一个字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 结果['ab', 'abb'] '?' 匹配前一个字符1次或0次 '{m}' 匹配前一个字符m次 '{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果'abb', 'ab', 'abb'] '|' 匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果'ABC' '(...)' 分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 结果 abcabca456c '\A' 只从字符开头匹配,re.search("\Aabc","alexabc") 是匹配不到的 '\Z' 匹配字符结尾,同$ '\d' 匹配数字0-9 '\D' 匹配非数字 '\w' 匹配[A-Za-z0-9] '\W' 匹配非[A-Za-z0-9] '\s' 匹配空白字符、\t、\n、\r , re.search("\s+","ab\tc1\n3").group() 结果 '\t' '(?P<name>...)' 分组匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})", "371481199306143242").groupdict("city") 结果{'province': '3714', 'city': '81', 'birthday': '1993'}
例子
import re
text = "JGood is a handsome boy, he is cool, clever, and so on..."
m = re.match(r"(\w+)\s", text)
if m:
print(m.group(0), '\n', m.group(1))#JGood
#JGood
else:
print ('not match')
test2="inet 地址:192.168.12.55 广播:192.168.12.255"
# a=re.match('.{3}',test2) #匹配3次
a=re.match('.{5,8}',test2) #匹配5到8次
print(a.group()) #inet 地址:
b=re.search("(\w{6})a(123|456)c","abcabca456c").groups() #groups分组 123|456 123或456
print(b) #('abcabc', '456')
c=re.search("(\d{2})(\d{2})(\d{2})(\d{4})",
"371481199206143421 name:alex").groups()#(\d{2})匹配两次打印两个
d=re.search("(\d){2}(\d){2}(\d){2}(\d){4}",
"371481199206143421 name:alex").groups()#(\d){2}匹配两次只打印最后一个
print(c) #('37', '14', '81', '1992')
print(d) #('7', '4', '1', '2')
最常用的匹配语法
re.match 从头开始匹配
re.search 匹配包含
re.findall 把所有匹配到的字符放到以列表中的元素返回
re.split 以匹配到的字符当做列表分隔符
re.sub 匹配字符并替换
re.complie
import re pattern = re.compile('[a-zA-Z]') result = pattern.findall('as3SiOPdj#@23awe') print result # ['a', 's', 'S', 'i', 'O', 'P', 'd', 'j', 'a', 'w', 'e']
反斜杠的困扰
与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\\\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r"\\"表示。同样,匹配一个数字的"\\d"可以写成r"\d"。有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
松散(verbose)的正则表达式
python默认使用紧凑的正则表达式(即普通的正则表达式),但为了提高正则表达式的可读性,我们可以使用松散的,如:
import re pattern = """ ^ #匹配开始 [0-9]{3,4} #匹配3个或者4个数字 -? #匹配0个或者1个-符号 [0-9]{7,8} #匹配7个或者8个数字 $ #匹配结束 """ #很显然上面的匹配式是用来匹配诸如029-82682345这样的中国电话号码的 re.search(pattern, '029-3456789', re.VERBOSE) #注意:此处的re.VERBOSE是用来标记此处用到的正则表达式是松散的,如果不加则会匹配
re.VERBOSE == re.X
计算器
需求:s= "1 - 2.0 * ((60.0-30 +(-40.0/5) * (9-2*5.0/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2))"
可以计算类似上述复杂的式子
流程图:
# s = '-1.9 - 2.09 * ( (60-30) +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4.01*3)/ (16-3*2) )' s='1-2*((60-30)+(-40.0/5)+(2*5/4*10))' import re def multiply_divide(s): #计算最简单的乘除 if '*' in s: ret = float(s.split("*")[0]) * float(s.split("*")[1]) elif "/" in s: ret = float(s.split("/")[0]) / float(s.split("/")[1]) # print(ret) return ret def add_sub(s): s=re.sub(r'\+\-','-',s) s=re.sub(r'\-\-','+',s) # print(s) # a=re.findall('[\d\.]|-|\+',s) #少写了个+, a=re.findall('([\d\.]+|-|\+)', s) if a[0]=='-': a[0]=a[0]+a[1] del a[1] sum=float(a[0]) for i in range(1, len(a),2): # 循环计算结果 if a[i] == '+' and a[i + 1] != '-': sum += float(a[i + 1]) elif a[i] == '+' and a[i + 1] == '-': sum -= float(a[i + 2]) elif a[i] == '-' and a[i + 1] == '-': sum += float(a[i + 2]) elif a[i] == '-' and a[i + 1] != '-': sum -= float(a[i + 1]) return sum def remove_md(s): if '*' not in s and "/" not in s: #如果没有乘除,递归结束 return s else: k=re.search(r"-?[\d\.]+[*/]-?[\d\.]+",s).group() # print(k) if len(re.findall(r'-',k))==2: s = s.replace(k,'+'+str(multiply_divide(k))) else: s=s.replace(k,str(multiply_divide(k))) return remove_md(s) def basic_operation(s): # 计算一个基本的4则运算 s = s.replace(' ','') #去空格 return add_sub(remove_md(s))# 调用前面定义的函数,先乘除,后加减 def calculate(s): #计算表达式 if not re.search("\([^()]+\)",s): return basic_operation(s) else: k=re.search("\([^()]+\)",s).group() #取括号最里层表达式 s=s.replace(k,str(basic_operation(k[1:len(k)-1])))#去括号 return calculate(s) #如果存在括号一直去括号 print('用eval计算出来的值为:{}\n计算器计算出来的值为:{}'.format(eval(s), calculate(s)))