(Python3) – 模式匹配与正则表达式

1.Python支持正则表达式,目测是ECMAScript的表达式。需要import re模块。使用re.compile(str,t)可以生成可以匹配str的RegEx对象,t是一组管道,可以通过按位或置位:

  • re.DOTALL:可以匹配所有的字符,包括换行
  • re.VERBOSE:可以添加给多行的str(通过’‘’可以添加多行文本)添加注释
  • re.IGNORECASE:忽略大小写。

2.‘\d'可以匹配一个数字,注意\在字符串中是特殊的字符需要转义,可以使用r避免二次转义。

3.分组:(\d\d\d)-(\d\d\d\d)使用分组就可以用group()方法获取匹配项。group()和group(0)表示获取整个匹配项,group(1)可以获取第一个分组。以此类推。(x1|x2|x3)使用管道可以匹配多个分组x1,x2和x3。

4.问号表示可选的匹配。+表示匹配项出现>=1次,而*出现>=0次。{m,n}表示可以出现m<=次数<=n,如果不指定m,n则表示n为上界或m为下界。

5.贪心匹配:默认得到最大的匹配项。例如(a){2,5},如果匹配aaaaa则会匹配aaaaa。如果使用(a){2,5)?则会最短的匹配:aa。

6.findall()方法:可以找到所有的匹配项。返回一个列表。如果每一次成功匹配的模式串中包含分组,那么列表的元素就都是一个元组,一个元组的每一个元素就是一个匹配的分组。

7.字符分类:

  • \w表示任何字字母、数字或下划线。\W就是非
  • \d表示0-9的一个数字\D就是非
  • \s表示空格、制表符或换行符。\S同理。

8.方括号[]可以是一组范围,表示匹配任何一个范围内的字符。方括号内的普通正则表达式的符号不会被解释。在左方括号后加上^表示不匹配任何存在于方括号中的字符。^或$可以指定匹配的序列的开始和结尾。例如,“[^abc]”可以匹配“plain”中的“plin”

9.通配字符:".*“可以匹配所有的除换行之外的字符。默认是贪心匹配的。如果不需要贪心,可以机上一个?号来匹配一个任意非换行字符即可。

10.替换sub(’str','bereplaced'):\1表示在替换中输入分组1、2、3……的文本。将bereplaced的所有的匹配项替换为str

11.几个例子:

#pattern match and regular expression
#coding=gb2312
import re
reg_str=r'\d\d\d-\d\d\d-\d\d\d\d'#regular expression
reg_obj=re.compile(reg_str)#regular expression(RegEx) object
mo=reg_obj.search('My phone:568-777-3333')
mo2=reg_obj.search('vaild : 5555-555-6666')
mo3=reg_obj.search('invaild : a12a-222-33')
print(mo.group())
print(mo2.group())#555-555-6666
#print(mo3.group())#error None does not have group()
#第二段 group() 等价于group(0)
reg_str2=r'(\d\d)-(\d\d)-(\d\d\d\d)'
reg_obj2=re.compile(reg_str2)
mo4=reg_obj2.search('23-66-6666')
print('1st:'+mo4.group(1)+'\n2nd'+mo4.group(2)+'\n3rd:'+mo4.group(3))
"""等价的语句:g1,g2,g3=mo4.groups()
print('groups():'+'1st:'+g1+'\n2nd'+g2+'\n3rd:'+g3)"""
#管道识别多个分组
app=r'app(ly|le|etite)'
regexapp=re.compile(app)
print('app'+regexapp.search('apply for porfessor').group(1))
#贪心的表达式匹配
greed=r'(Ha\?){3,5}'#3<=Ha?<=5次出现
regexgreed=re.compile(greed)
print(regexgreed.search('Ha?Ha?Ha?Ha?Ha?').group(0))#如果有二义性,那么就会匹配最长的
#非贪心的匹配
nogreed=r'(Ha\?){3,5}?'#3<=Ha?<=5次出现 注意末尾的“?”
regexnogreed=re.compile(nogreed)
print(regexnogreed.search('Ha?Ha?Ha?Ha?Ha?').group(0))#找到能匹配的就会停止搜索 输出Ha?Ha?Ha?
#findall的使用
sub=r'(\d\d\d)-(\d\d)'
nosub=r'\d\d\d-\d\d'
regexsub=re.compile(sub)
regexnosub=re.compile(nosub)
print(regexsub.findall('555-22:666-22'))#由于有子的匹配项,所以有两个匹配项每一个匹配项构成一个元组:[('555', '22'), ('666', '22')]
print(regexnosub.findall('555-22:666-22'))#由于没有子匹配项,也会返回一个列表,每一个元素就是一个字符串
#.*的匹配 .表示匹配一个任意除换行的字符 *出现>=0   默认贪心
dotstar=r'File:(.*),Extra:(.*)'
mo5=re.compile(dotstar).search('File:hahaha,Extra:txt')
print(mo5.group(1)+'.'+mo5.group(2))
#非贪心的匹配
dotstarnogreed=r'<.*?>'#去掉问号就可以匹配<abcd>dfvdvd>
print(re.compile(dotstarnogreed).search('<abcd>dfvdvd>').group())
#regular match demo 2
#coding=gb2312
#替换所有的Agent
import re
str1=r'Agent \w*'#替换Agent 且后面要接一个空格
rep=re.compile(str1)
print(rep.sub('***','Agent ffggg Agent dfafrdfdf Agent '))
#sub替换2 保留第一个字符
str2=r'Agent (\w)w*'
print(re.compile(str2).sub(r'\1***','Agent Liu Agent Wang Agent Fang'))

应用:获得电话号码和Email:

#match email and phone from clipboard
#coding=gb2312
import re
import pyperclip
str_phone=r'''
(\d{1,3})#area 注意要设置一个最小的长度
(\s|-|.)#separator
(\d{1,11})#phone number
'''
str_email=r'''(
[0-9a-zA-Z-_]+#usename
@#symbol
[0-9a-zA-Z-_]+#domain name
(\.[0-9a-zA-Z-_]{2,4}))
'''
stre=str(pyperclip.paste())
print('剪贴板内容:'+stre)
regex_phone=re.compile(str_phone,re.VERBOSE)
regex_email=re.compile(str_email,re.VERBOSE)
mo1=regex_phone.search(stre)
mo2=regex_email.search(stre)
print('Phone Number:'+mo1.group())
print('Email:'+mo2.group())

参考: