Python 正则表达模块详解(7)
Python 的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承.Python是纯粹的自由软件,源代码和解释器CPython遵循 GPL(GNU General Public License)协议.关于python的哲学:python崇尚:"优雅"、"明确"、"简单",Python是用最简单最优雅最明确的方法来解决问题.
正则表达式(Regluar Expressions)又称规则表达式,这个概念最初是由Unix中的工具软件(如sed 和 grep)普及开的,正则表达式在代码中常简写为RES,它本质上是一个小巧的、高度专用的编程语言,许多程序设计语言都支持通过正则表达式进行字符串操作,通俗的来讲,正则就是用一些具有特殊含义的符号组合到一起来描述字符或者字符串的方法,正则模块内嵌在Python中,并通过re模块实现,正则表达式模式被编译成一系列的字节码,然后由用C编写的匹配引擎执行. 正则表达式的主要应用对象是文本,其最基础的功能是文本匹配,而文本是由一个个的字符组成,因此正则表达式实际上是对字符的匹配,正则表达式中的字符分为 通用字符匹配
正则符号( >>> import re >>> re.search("he.o","helo hello helllo hellllo").group() 'helo' >>> re.search("he...o","helo hello helllo hellllo").group() 'helllo' >>> re.findall("he.o","helo heao hello helllo hellllo") ['helo','heao'] 正则符号( >>> re.search("..t","hellot lysharkn").group() 'lot' >>> re.search("t","hellot lysharkn").group() 't' >>> re.search("t","hellot lysharkn").group() 't' >>> re.search(r"","hellolyshark").group() '' 正则符号( >>> re.search("[0-9]","hello 1,2,3,4,5").group() '1' >>> re.findall("[0-9]",5") ['1','2','3','4','5'] >>> re.search("[^0-9]",5").group() 'h' >>> re.search("[a-z]",5").group() 'h' >>> re.search("^[a-z]",5").group() 'h' >>> re.search("[^a-z]",5").group() ' ' >>> re.search("[^A-Z]",5").group() 'h' 通用边界匹配
正则符号( >>> re.search(r"^h","hello world") <re.Match object; span=(0,1),match='h'> >>> re.search(r"^h","hello world").group() 'h' >>> re.search(r"world$","hellonworld") <re.Match object; span=(6,11),match='world'> >>> re.search(r"world$","hellonworld").group() 'world' 正则符号( >>> re.findall("ab*","abccba23acbcabb") ['ab','a','abb'] 正则符号( >>> re.findall("ab+",'abb'] 正则符号( >>> re.findall("ab?",abb,abcd,acd,abc") ['ab','ab','ab'] >>> re.findall("ab?",abcde") ['ab','ab'] 正则符号( >>> re.search("abc|ABC","ABCBabcCD").group() 'ABC' >>> re.findall("abc|ABC","ABCBabcCD") ['ABC','abc'] 正则符号( >>> re.search("hello{2}",helloo,hellooo,helloooo").group() 'helloo' >>> re.search("hello{3}",helloooo").group() 'hellooo' 正则符号( >>> re.search("hello{1,2}",helloooo").group() 'hello' >>> re.findall("hello{1,helloooo") ['hello','helloo','helloo'] 正则符号( >>> number = "371481199306143242" >>> re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})",number).groupdict() {'province': '3714','city': '81','birthday': '1993'} >>> re.search("(?P<name>[a-zA-Z]+)(?P<age>[0-9]+)","lyshark22").groupdict("temp") {'name': 'lyshark','age': '22'} 常用匹配函数
regex.match(): 从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None. match(pattern,string,flags=0) # pattern: 正则模型 # string : 要匹配的字符串 # falgs : 匹配模式 #------------------------------------------------ # 未分组情况下. >>> origin = "hello alex bcd abcd lge acd 19" >>> >>> ret = re.match("hw+",origin) >>> print(ret.group()) #获取匹配到的所有结果 >>> print(ret.groups()) #获取模型中匹配到的分组结果 >>> print(ret.groupdict()) #获取模型中匹配到的分组结果 #------------------------------------------------ # 有分组情况下. 提取匹配成功的指定内容(先匹配成功全部正则,再匹配成功的局部内容提取出来) >>> ret = re.match("h(w+).*(?P<name>d)$",origin) >>> print(r.group()) #获取匹配到的所有结果 >>> print(r.groups()) #获取模型中匹配到的分组结果 >>> print(r.groupdict()) #获取模型中匹配到的分组中所有执行了key的组 regex.search(): 搜索整个字符串去匹配第一个符合条件的数据,未匹配成功返回None. >>> origin = "hello alex bcd abcd lge acd 19" >>> >>> re.search("^hw+",origin).group() #匹配开头是h的后面是任意字符的 'hello' >>> re.search("aw+",origin).group() #匹配a开头后面是任意字符的 'alex' >>> re.search("(?P<name>aw+)",origin).groupdict() {'name': 'alex'} #分组匹配并过滤出alex >>> re.search("(?P<姓名>[a-zA-Z]+)(?P<年龄>[0-9]+)","lyshark22").groupdict() {'姓名': 'lyshark','年龄': '22'} #匹配字符串,并分组打印出结果 regex.findall(): 获取非重复的匹配列表,如果有一个组则以列表形式返回,且每一个匹配均是字符串,空的匹配也会包含在结果中. >>> origin = "hello alex bcd abcd lge acd 19" >>> re.findall("alw+",origin) ['alex'] #匹配到单个结果,则以单列表返回 >>> re.findall("aw+",origin) ['alex','abcd','acd'] #匹配到多个结果,则以列表形式返回 regex.sub(): 先匹配查找结果,然后进行字串的替换,也就是替换匹配成功的指定位置字符串. sub(pattern,repl,count=0,flags=0) # pattern: 正则模型 # repl : 要替换的字符串或可执行对象 # string : 要匹配的字符串 # count : 指定匹配个数 # flags : 匹配模式 >>> origin = "hello alex bcd abcd lge acd 19" >>> re.sub("a[a-z]+","999999",origin,1) #匹配以a开头则字串,并替换成9999,替换1次 'hello 999999 bcd abcd lge acd 19' >>> re.sub("a[a-z]+",2) #匹配以a开头则字串,替换2次 'hello 999999 bcd 999999 lge acd 19' regex.split(): 字符串切割函数,用来实现对指定字符串的分割工作,根据正则匹配分割字符串. split(pattern,maxsplit=0,flags=0) # pattern: 正则模型 # string : 要匹配的字符串 # maxsplit:指定分割个数 # flags : 匹配模式 >>> origin = "hello alex bcd abcd lge acd 19" >>> re.split("alex",1) #无分组切割 ['hello ',' bcd abcd lge acd 19'] >>> re.split("(alex)",1) #有分组,以alex最为分隔符,切割字符串 ['hello ','alex',' bcd abcd lge acd 19'] 常用匹配: 下面举几个小例子,分别用来匹配IP地址,手机号,和邮箱地址. IP: ^(25[0-5]|2[0-4]d|[0-1]?d?d)(.(25[0-5]|2[0-4]d|[0-1]?d?d)){3}$ 手机号: ^1[3|4|5|8][0-9]d{8}$ 邮箱: [a-zA-Z0-9_-][email?protected][a-zA-Z0-9_-]+(.[a-zA-Z0-9_-]+)+ Flage 标识位re.DOTALL # 正则表达式默认以单行开始匹配的 import re def re_pattern_syntax(): # .表示任意单一字符 # *表示前一个字符出现>=0次 # re.DOTALL就可以匹配换行符n,默认是以行来匹配的 print(re.match(r'.*','abcnedf').group()) print('*' * 80) print(re.match(r'.*','abcnedf',re.DOTALL).group()) if __name__ == '__main__': re_pattern_syntax() re.MULTILINE # 正则表达式默认以单行开始匹配的 import re def re_pattern_syntax1(): # ^表示字符串开头(单行) # re.MULTILINE多行匹配字符串开头 print(re.findall(r'^abc','abcnedf')) print('*' * 80) print(re.findall(r'^abc','abcnabc',re.MULTILINE)) def re_pattern_syntax2(): # $表示字符串结尾 # re.MULTILINE表示行的结束 print(re.findall(r'abcd$','abc1nabc2')) print('*' * 80) print(re.findall(r'abcd$','abc1nabc2',re.MULTILINE)) if __name__ == '__main__': re_pattern_syntax1() re_pattern_syntax2() ?非贪婪模式 import re def re_pattern_syntax4(): # greedy贪婪/non-greedy非贪婪,默认的是贪婪的匹配 s = '<H1>title</H1>' print(re.match(r'<.+>',s).group()) #贪婪模式会匹配尽量多的匹配 print(re.match(r'<.+?>',s).group()) #非贪婪模式匹配尽量少的匹配 print(re.match(r'<(.+)>',s).group(1)) print(re.match(r'<(.+?)>',s).group(1)) def re_pattern_syntax5(): # {m}/{m,}/{m,n} print(re.match(r'ab{2,4}','abbbbbbb').group()) #贪婪模式尽量匹配多 print(re.match(r'ab{2,4}?','abbbbbbb').group()) #非贪婪模式尽量匹配少 print('*' * 80) if __name__ == '__main__': re_pattern_syntax4() re_pattern_syntax5() re.I/re.IGNORECASE import re def re_pattern_flags(): # re.I/re.IGNORECASE print(re.match(r'(Name)s*:s*(w+)','NAME : Joey',re.IGNORECASE).groups()) print('*' * 80) if __name__ == '__main__': re_pattern_syntax_meta_char() re.VERBOSE import re def re_pattern_flags1(): # re.VERBOSE此标识位可以添加注释/re.compile s = 'the number is 20.5' r = re.compile(r''' d+ # 整数部分 .? # 小数点,可能包含也可能不包含 d* # 小数部分,可选 ''',re.VERBOSE) print(re.search(r,s).group()) print(r.search(s).group()) print('*' * 80) if __name__ == '__main__': re_pattern_syntax_meta_char1() 有无分组比较re.mach() # 无分组 r = re.match("hw+",origin) print(r.group()) # 获取匹配到的所有结果 print(r.groups()) # 获取模型中匹配到的分组结果 print(r.groupdict()) # 获取模型中匹配到的分组结果 # 有分组 # 为何要有分组?提取匹配成功的指定内容(先匹配成功全部正则,再匹配成功的局部内容提取出来) r = re.match("h(w+).*(?P<name>d)$",origin) print(r.group()) # 获取匹配到的所有结果 print(r.groups()) # 获取模型中匹配到的分组结果 print(r.groupdict()) # 获取模型中匹配到的分组中所有执行了key的组 re.search() # 无分组 r = re.search("aw+",origin) print(r.group()) # 获取匹配到的所有结果 print(r.groups()) # 获取模型中匹配到的分组结果 print(r.groupdict()) # 获取模型中匹配到的分组结果 # 有分组 r = re.search("a(w+).*(?P<name>d)$",origin) print(r.group()) # 获取匹配到的所有结果 print(r.groups()) # 获取模型中匹配到的分组结果 print(r.groupdict()) # 获取模型中匹配到的分组中所有执行了key的组 re.findall() # 无分组 r = re.findall("aw+",origin) print(r) # 有分组 origin = "hello alex bcd abcd lge acd 19" r = re.findall("a((w*)c)(d)",origin) print(r) re.split() # 无分组 origin = "hello alex bcd alex lge alex acd 19" r = re.split("alex",1) print(r) # 有分组 origin = "hello alex bcd alex lge alex acd 19" r1 = re.split("(alex)",1) print(r1) r2 = re.split("(al(ex))",1) print(r2) 常用例子 import re print(re.findall(r'(d+)-([a-z])','34324-dfsdfs777-hhh')) # [('34324','d'),('777','h')] print(re.search(r'(d+)-([a-z])','34324-dfsdfs777-hhh').group(0)) # 34324-d 返回整体 print(re.search(r'(d+)-([a-z])','34324-dfsdfs777-hhh').group(1)) # 34324 获取第一个组 print(re.search(r'(d+)-([a-z])','34324-dfsdfs777-hhh').group(2)) # d 获取第二个组 print(re.search(r'(d+)-([a-z])','34324-dfsdfs777-hhh').group(3)) # IndexError: no such group print(re.search(r"(jason)kk1","xjasonkkjason").group()) #1表示应用编号为1的组 jasonkkjason print(re.search(r'(d)gg1','2j333gg3jjj8').group()) # 3gg3 1表示使用第一个组d # 下面的返回None 为什么是空?而匹配不到3gg7,因为1的不仅表示第一组,而且匹配到的内容也要和第一组匹配到的内容相同,第一组匹配到3,第二组匹配到7 不相同所以返回空 print(re.search(r'(d)gg1','2j333gg7jjj8')) print(re.search(r'(?P<first>d)abc(?P=first)','1abc1')) # 1abc1 声明一个组名,使用祖名引用一个组 r=re.match('(?P<n1>h)(?P<n2>w+)','hello,hi,help') # 组名的另外一种用法 print(r.group()) # hello 返回匹配到的值 print(r.groups()) # ('h','ello')返回匹配到的分组 print(r.groupdict()) # {'n2': 'ello','n1': 'h'} 返回分组的结果,并且和相应的组名组成一个字典 # 分组是从已经匹配到的里面去取值 origin ="hello alex,alex" print(re.findall(r'(a)(w+)(x)',origin)) # [('a','le','x'),('a','x')] print(re.findall(r'aw+',origin)) # ['alex','acd','alex'] print(re.findall(r'a(w+)',origin)) # ['lex','cd','lex'] print(re.findall(r'(aw+)',origin)) # ['alex','alex'] print(re.findall(r'(a)(w+(e))(x)',origin)) # [('a','e','x')] r=re.finditer(r'(a)(w+(e))(?P<name>x)',origin) for i in r : print(i,i.group(),i.groupdict()) ''' [('a','x')] <_sre.SRE_Match object; span=(6,10),match='alex'> alex {'name': 'x'} <_sre.SRE_Match object; span=(15,19),match='alex'> alex {'name': 'x'} ''' print(re.findall('(w)*','alex')) # 匹配到了alex、但是4次只取最后一次即 x 真实括号只有1个 print(re.findall(r'(w)(w)(w)(w)','alex')) # [('a','l','x')] 括号出现了4次,所以4个值都取到了 origin='hello alex sss hhh kkk' print(re.split(r'a(w+)',origin)) # ['hello ','lex',' sss hhh kkk'] print(re.split(r'aw+',origin)) # ['hello ',' sss hhh kkk'] (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |