美文网首页Python开发
python(01) 正则表达式

python(01) 正则表达式

作者: 灼灼2015 | 来源:发表于2016-10-16 23:13 被阅读92次

    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编程快速上手-让繁琐工作自动化》

    相关文章

      网友评论

      • 一斩z:我仿写了一段 不知道为什么匹配不出来,能帮我看看吗

        #coding = utf - 8
        import pyperclip
        import re

        #匹配文本里的ASIN

        text = str(pyperclip.paste())

        ASINRegex = re.compile(r'B07/w+')

        matches = []

        for groups in ASINRegex.findall(text):
        #print groups
        matches.append(groups[0])

        #复制到剪切板
        if len(matches) > 0:
        pyperclip.copy('\n'.join(matches))
        print('copied to clipboard:')
        print('\n'.join(matches))
        else:
        print('Not Find')
        一斩z:@灼灼2015 哇 太感谢了。
        灼灼2015:ASINRegex = re.compile(r'B07/w+') 改成 ASINRegex = re.compile(r'B07\w+')

      本文标题:python(01) 正则表达式

      本文链接:https://www.haomeiwen.com/subject/yafayttx.html