<automate the boring stuff with python>---第七章 正则实例&正则贪心&匹配电话号码和邮箱
第七章先通过字符串查找电话号码,比较了是否使用正则表达式程序的差异,明显正则写法更为简洁、易扩展。
模式:3 个数字,一个短横线,3个数字,一个短横线,再是4 个数字。例如:415-555-4242
1 import re 2 ''' 3 不用正则查找模式,匹配3个数字,1个短横线,3个数字,1个短横线,4个数字 4 ex. 111-222-3334 5 ''' 6 7 def isPhoneNo(text): 8 if len(text) != 12: 9 return False 10 for i in range(0,3): 11 if not text[i].isdecimal(): 12 return False 13 if text[3] != '-': 14 return False 15 for i in range(4,7): 16 if not text[i].isdecimal(): 17 return False 18 if text[7] != '-': 19 return False 20 for i in range(8,12): 21 if not text[i].isdecimal(): 22 return False 23 return True 24 25 ''' 26 用正则表达式匹配上述模式 27 ''' 28 def regPhoneNo(text): 29 phoneNoReg=re.compile(r'\d\d\d-\d\d\d-\d\d\d\d') 30 res=phoneNoReg.search(text) 31 if res != None: 32 print('phone No find by reg: '+ res.group()) 33 34 print(isPhoneNo('123-122-9090')) 35 print(isPhoneNo('1234123321')) 36 msg = 'call me at 415-443-1111 tomorrow. 415-443-2222 is my office' 37 for i in range(len(msg)): 38 tmp = msg[i:i+12] 39 if isPhoneNo(tmp): 40 print('phone No find: ' + tmp) 41 regPhoneNo(tmp) 42 print('msg find end')
Python 的正则表达式默认是“贪心”的,这表示在有二义的情况下,它们会尽可能匹配最长的字符串。
花括号的“非贪心”版本匹配尽可能最短的字符串,即在结束的花括号后跟着一个问号
实例:
''' 例子说明Python的贪心和非贪心匹配结果 ''' def showGreedReg(): greedReg=re.compile(r'(ha){3,5}') nonGreedReg=re.compile(r'(ha){3,5}?') inp='hahahahahah' r1=greedReg.search(inp) r2=nonGreedReg.search(inp) print('greed reg res: '+r1.group()) print('nongreed reg res: '+r2.group()) showGreedReg()
第7章的项目为电话号码和邮箱的正则提取,剪切板部分此处省略。
1 import pyperclip, re 2 phoneReg=re.compile(r'''( 3 (\d{3}|\(\d{3}\))? #area code 4 (\s|-|\.)? #separator 5 (\d{3}) #first 3 digits 6 (\s|-|\.)? #separator 7 (\d{4}) #last 4 digits 8 (\s*(ext|x|ext.)\s*(\d{2,5}))? 9 )''', re.VERBOSE 10 ) 11 12 emailReg=re.compile(r'''( 13 [a-zA-Z0-9_-]+ #username 14 @ #@ 15 [a-zA-Z0-9_-]+ #domain name 16 (\.[a-zA-Z]{2,4}) 17 )''', re.VERBOSE 18 )
电话号码从一个“可选的”区号开始,所以区号分组跟着一个问号。
因为区号可能只是3 个数字(即\d{3}),或括号中的3 个数字(即\(\d{3}\)),所以应该用管道符号连接这两部分。
可以对这部分多行字符串加上正则表达式注释# Area code,帮助你记忆(\d{3}|\(\d{3}\))?要匹配的是什么。
电话号码分割字符可以是空格(\s)、短横(-)或句点(.),所以这些部分也应该用管道连接。
这个正则表达式接下来的几部分很简单:3 个数字,接下来是另一个分割符,接下来是4 个数字。
最后的部分是可选的分机号,包括任意数目的空格,
接着ext、x 或ext.,再接着2 到5 位数字。
E-mail 地址的用户名部分是一个或多个字符,字符可以包括:小写和大写字母、数字、句点、下划线、百分号、加号或短横。
可以将所有这些放入一个字符分类:[a-zA-Z0-9._%+-]。
域名和用户名用@符号分割,域名允许的字符分类要少一些,只允许字母、数字、句点和短横:[a-zA-Z0-9.-]。
最后是“dot-com”部分(技术上称为“顶级域名”),它实际上可以是“dot-anything”。它有2 到4 个字符。
re.VERBOSE,忽略正则表达式字符串中的空白符和注释
至此,第七章内容结束,实践项目 强口令检测 见下期博客