Python开发

python(01) 正则表达式

2016-10-16  本文已影响92人  灼灼2015

Cory Doctorow声称 应该在教授编程之前,先教授正则表达式:
知道[正则表达式]可能意味着用3步解决一个问题,而不是用3000步。如果你是一个技术怪侠,别忘了用几次击健就能解决的问题,其他人需要数天的繁琐工作才能解决,而且他们容易犯错。

练习:在字符串中查找电话号码,已知:3个数字,一个短横线,3个数字,一个短横线,再是4个数字,如:415-555-4242。

  1. 不用正则表达式
def isPhoneNumber(text):
    if len(text) != 12:
        return False
    for i in range(0,3):
        if not text[i].isalnum():
            return False
        if text[3] != '-':
            return False
    for i in range(4,7):
        if not text[i].isalnum():
            return False
        if text[7] != '-':
            return False
    for i in range(8,12):
        if not text[i].isalnum():
            return False
    return True

单个调用

print('415-555-4242 is a phone number:')
print(isPhoneNumber('415-555-4242'))
print('Moshi moshi is a phone number:')
print(isPhoneNumber('Moshi moshi'))

循环调用

message = 'Call me at 415-555-1011 tomorrow. 415-555-9999 is my office.'
for i in range(len(message)):
    chunk = message[i:i+12]
    if isPhoneNumber(chunk):
        print('Phone number found:' + chunk)
print('Done')

执行结果

415-555-4242 is a phone number:
True
Moshi moshi is a phone number:
False
Phone number found:415-555-1011
Phone number found:415-555-9999
Done
Process finished with exit code 0
  1. 改成正则表达式
import re
phoneNumberRegex = re.compile(r'\\\\d{3}-\\\\d{3}-\\\\d{4}')
mo = phoneNumberRegex.search('My number is 415-555-4242')
print('Phone number found: ' + mo.group())

执行结果

Phone number found: 415-555-4242

总结使用正则表达式四步

  1. 用import re 导入正则表达式模块。
  2. 用re.compile()函数创建一个Regex对象(使用原始字符串)
  3. 向Regex对象的search()方法传入想查找的字符串。它返回一个Match对象。
  4. 调用Match对象的group()方法,返回实际匹配文本的字符串。
    推荐学习:http://regexpal.com/
  1. 更强大的功能
  1. 利用括号分组
    分组:(\\d\\d\\d)-(\\d\\d\\d-\\d\\d\\d\\d)
    group()=group(0)匹配所有
    group(1) 匹配(\\d\\d\\d)
    group(2) 匹配(\\d\\d\\d-\\d\\d\\d\\d)
    groups()多个值的元组--使用的多重复制的技巧
    \\(和\\)转义字符匹配实际的括号

  2. 用管道匹配多个分组
    r'Batman|Tina Fey'
    \\|匹配真正的管道字符

3)用问号实现可选匹配
r'Bat(wo)?man'
匹配0次或一次
\\?匹配真正的问号字符

4)用星号匹配零次或多次
r'Bat(wo)man'
\\
匹配真正的星号字符

5)用加号匹配一次或多次
r'Bat(wo)+man'
\\+匹配真正的加号字符

6)用花括号匹配特定次数
r'(Ha){3}' --重复3次
r'(Ha){3,5}' --重复3到5次 ----贪心匹配,如有可能重复5次
r'(Ha){,5}'--重复0到5次
r'(Ha){3,}'--重复3次或更多次
r'(Ha){3,5}?' -----非贪心匹配 ,重复3次就可以啦

  1. search()和findall()区别
    search--返回第一次匹配的文字
    findall()--返回所有匹配的组

  2. 字符分类
    \\d ----------0到9的任何数字
    \\D----------除0-9的数字以外的任何字符
    \\w---------任何字母、数字或下划线字符
    \\W---------除字母、数字和下划线以外的任何字符
    \\s----------空格、制表符或换行符--空白
    \\S---------除空格、制表符和换行符以外的任何字符
    成对出现,只记三个即可(d w s),其他三个反推。

  3. 使用[]建立自己的字符分类
    [] 中0-5表示从0到5
    插入字符--表示除了这个字符以外的任意字符

10)插入字符和美元字符
插入字符-----表示以这个为开始
美元字符-----表示以这个为结束

  1. 通配字符
    句点字符. 匹配一个字符(除换行之外的)
    点星.* 匹配所有字符 ---贪心模式
    .? 非贪心模式
    re.compile('.
    ',re.DOTALL) 匹配所有包括换行

书籍看到这里,看到作者总结,真的特别简洁,差距就是连整理都不到更好

python 正则表达式.JPG
  1. 更复杂更强大的功能
  1. 用sub()方法替换字符串
>>> namesRegex = re.compile(r'Amy \\\\w+')
>>> namesRegex.sub('QingQian',' Amy like apple')
' QingQian apple'
>>> namesRegex = re.compile(r'Amy')
>>> namesRegex.sub('QingQian',' Amy like apple')
' QingQian like apple'
>>>

2)管理复杂正则表达式

phoneRegex = re.compile(r'''(
(\\\\d{3}|\\\\(\\\\d{3}\\\\))?                # area code
(\\\\s|-|\\\\.)?                         # separator
\\\\d{3}                              # first 3 digits
(\\\\s|-|\\\\.)                           # separator
\\\\d{4}                               # last 4 digits
(\\\\s*(ext|x|ext.)\\\\s*\\\\d{2,5})?   # extension
)''',re.VERBOSE)

代码应该就有代码的优雅

  1. 传递多个参数
someRegexValue = re.compile('foo' , re.IGNORECASE | re.DOTALL | re.VERBOSE)

compile()默认只接受一个值作为第二参数,通过管道| 对变量做组合进行传递。

  1. 实践:电话号码和E-mail地址提取程序
    在网页/文章中找出所有电话号码和E-mail地址。
    作为程序员拿到需求后,先做个简单的分析/拆解,理解真正要做的是什么,另:培养框架感
    任务分析
  1. 取得文本
  2. 在文本中找出电话号码和E-mail
  3. 将找到的内容保存起来
    对应着程序语言
    1)复制粘贴功能
    2)创建正则表达式:一个电话号码 和一个E-mail
    3)将匹配的内容-按一定格式存放到字符串,方便复制
    4)找不到相关的内容时 给出相应的提示
import re
phoneNumberRegex = re.compile(r'''(
    (\d{3}|\(\d{3}\))?      # area code
    (\s|-|\.)?               # separator
    (\d{3})                    # first 3 digits
    (\s|-|\.)               # separator
    (\d{4})                 # last 4 digits
    (\s*(ext|x|ext.)\s*(\d{2,5}))?  # extension
    )''', re.VERBOSE | re.DOTALL)
emailRegex = re.compile(r'''(
      [a-zA-Z0-9._%+-]+
       @
       [a-zA-Z0-9.-]+
       (\.[a-zA-Z]{2,4})
      )''', re.VERBOSE | re.DOTALL)

text = 'I am mary, my phone-number is 411-435-9999,my email address is qqin@126.com.cn hi ' \
       'my phone-number is 412-222-4949,my email address is qingqian@sohu.com hihihi.'
matches = []
for phones in phoneNumberRegex.findall(text):
    phoneNumber = '-'.join([phones[1],phones[3],phones[5]])
    if phones[8] != '':
        phoneNumber += ' x' + phones[8]
    matches.append(phoneNumber)
for emails in emailRegex.findall(text):
    matches.append(emails[0])
if len(matches) > 0:
    print('\n'.join(matches))
else:
    print('No phone numbers or email address found.')

运行结果:

411-435-9999
412-222-4949
qqin@126.com.cn
qingqian@sohu.com

所有学习都是从模仿开始的,本文照搬《Python编程快速上手-让繁琐工作自动化》

上一篇下一篇

猜你喜欢

热点阅读