美文网首页
Python碎碎念(2):正则表达式

Python碎碎念(2):正则表达式

作者: xxlee | 来源:发表于2019-03-06 15:18 被阅读0次

    转载请在文章起始处注明出处,谢谢。

    文章转自本人之前博客

    0. 写在前面

    正则表达式,是一种强大的匹配模式。

    1. 使用正则表达式的步骤

    a.用import re导入正则表达式模块;
    
    b.用re.compile()函数创建一个Regex对象(记得使用原始字符串r);
    
    c.向Regex对象的search()方法传入想查找的字符串,它返回一个Match()对象;
    
    d.调用Match()对象的group()方法,返回实际匹配文本的字符串。
    
    

    例如:

    import re 
    
    phoneNumRegex = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d')
    
    mo = phoneNumRegex.search('My number is 123-456-7890.')  #mo是一个通用名称,用于Match对象。
    
    print('Phone number found:' + mo.group())
    
    

    注意:除了search()方法外,还有findall()方法。search()返回一个Match()对象,而findall()返回一组字符串列表,包含被查找字符串中所有匹配。若正则表达式中有分组,则返回一个元组的列表。

    2. 正则表达式匹配更多模式

    2.1利用括号进行分组

    添加括号可以在正则表达式中创建“分组”,使用group()匹配对象的方法,从分组中获得匹配文本。

    例如:

    (\d\d\d)-(\d\d\d-\d\d\d\d)  如:123-456-7890
    
    group(1) ----> '123'
    group(2) ----> '456-7890'
    group(0)或group() ----> '123-456-7890'
    groups() ---->  ('123','456-7890')   #可以使用多重赋值的方法
    
    

    2.2用管道匹配多个分组

    字符’|’被称为管道,用来匹配许多表达式中的一个。

    2.3问号实现可选匹配

    ‘?’匹配之前分组零次或一次。

    2.4星号匹配零次或多次

    ‘*’匹配之前的分组零次或多次。

    2.5加号匹配一次或多次

    ‘+’匹配之前的分组一次或多次

    2.6花括号匹配特定的次数

    例如:

    (ha){3} ----> 'hahaha'
    
    (ha){3,5} ---->  'hahaha'、'hahahaha'、'hahahahaha'  
    
    (ha){3,5}相当于管道匹配((hahaha)|(hahahaha)|(hahahahaha))
    
    

    3. 贪心和非贪心匹配

    Python正则表达式默认“贪心”匹配,即匹配最长的字符串。

    花括号的“非贪心”匹配,匹配最短的字符串,要在结束的花括号后跟一个问号。

    例如:

    (ha){3,5}  #贪心匹配
    
    (ha){3,5}?  #非贪心匹配
    
    

    4. 字符分类

    \d 0~9的任意数字
    
    \D 除0~9的数字以外任何字符
    
    \w 任何字母、数字、下划线字符(可以认为是匹配“单词”字符)
    
    \W 除字母、数字、下划线字符以外的任何字符
    
    \s 空格、制表符、换行符(可以认为是匹配“空白”字符)
    
    \S 除空格、制表符、换行符以外的任何字符
    
    

    例如:

    [0-5] ----> 0~5
    
    \d+\s\w+ ----> 12 words
    
    

    5. 建立自己的字符分类

    使用方括号[]定义自己的字符分类。

    例如:

    [aeiouAEIOU]匹配所有元音字符,不论大小。
    
    

    注意:方括号内的普通正则表达式符号不会被解释,也就是说不需要加\。

    在字符分类的左括号后加^,表示非字符类。

    例如:

    [^aeiouAEIOU]表示匹配所有的非元音字符。
    
    

    6. 插入字符(^)和美元字符($)

    在正则表达式开始处使用插入字符(^),表明匹配必须发生在被查找文本开始处。

    在正则表达式末尾处加上美元字符($),表明字符串必须以这个正则表达式的模式结束。

    例如:

    正则表达式r'^\d+$'表明开始和末尾都是数字。
    
    

    7. 通配字符

    正则表达式中句点(.)被称为通配字符,匹配除换行之外的所有单个字符。

    注意:句点字符只匹配一个字符。

    7.1 点星匹配所有字符

    .* 表示任意文本,使用的是贪心匹配,若想使用非贪心匹配,则需要在后面加?,即.*?。

    7.2 句点字符匹配换行

    .* 匹配所有除换行外的字符,通过传入re.DOTALL作为re.compile()的第二个参数,可以让句点字符匹配所有字符,包括换行符。

    8. 不区分大小写的匹配

    要让正则表达式不区分大小写,可以向re.compile()中传入re.IGNORECASE或re.I,作为第二个参数。

    9. 用sub()方法替换字符串

    Rxgex对象的sub()方法,传入两个参数,第一个参数是一个字符串,用来取代发现的匹配;第二个参数是正则表达式。sub()方法返回替换完成的字符串。

    例如:

    namesRegex = re.compile(r'Agent \w+')
    
    namesRegex.sub('CENSORED','Agent Alice gave the secret documents to Aengt Bob.')
    
    

    有时候,可能需要使用匹配文本本身,作为替换的一部分,在sub()的第一个参数中输入\1\2\3..,表示在替换中输入分组1、2、3..的文本。

    例如:

    import re
    agentnameRegex = re.compile(r'Agent (\w)\w*')
    print(agentnameRegex.sub(r'\1@@','Agent a told Agent b that Agent c knew Agent d was a double agent.'))
    
    

    输出:

    a@@ told b@@ that/ c@@ knew d@@ was a double agent.
    
    

    10. 管理复杂的正则表达式

    若正则表达式比较长、复杂,想忽略正则表达式中的空白符和注释,可以使用re.VERBOSE,作为第二个参数。

    例如:

    import re
    
    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)
    
    print(phoneRegex.findall('(123) 456-7890 ext. 123  123-456-7890'))
    
    

    输出:

    [('(123) 456-7890 ext. 123', '(123)', ' ', '-', ' ext. 123', 'ext.'), ('123-456-7890', '123', '-', '-', '', '')]
    
    

    11. 项目:电话号码和Email地址提取程序

    假设有一个无聊的任务,需要在一篇长的网页或者文章中,找出所有电话号码和邮件的地址。如果手动翻页,可能需要查找很长时间,如果有一个程序,可以在剪贴板的文本中查找电话号码和Email地址,那就只需要按一下Ctrl-A选择所有文本,按下Ctrl-C将它复制到剪贴板,然后运行程序。就可以自动找到电话号码和Email地址,替换掉剪贴板中的文本。

    import re,pyperclip
    
    #为电话号码创建一个正则表达式
    
    phoneRegex = re.compile(r'''(
        (\d{3,4}|\(\d{3,4}\))?    #area code or telphone number
        (\s|-|\.)?             #separator
        (\d{8})                 #8 digits
        (\s*(ext|x|ext.)\s*\d{2,5})? #extension
        )''', re.VERBOSE)
    
    #为Email创建一个正则表达式
    
    emailRegex = re.compile(r'''(
        [a-zA-Z0-9._%+-]+    #username
        @                    
        [a-zA-Z0-9.-]+       #domain name
        (\.[a-zA-Z]{2,4})    #dot-something
        )''',re.VERBOSE)
    
    #在剪贴板文本中找到所有匹配
    
    text = str(pyperclip.paste())
    
    matches = []
    
    for groups in phoneRegex.findall(text):
        phoneNum = ' '.join([groups[1],groups[3]])
        if groups[4] != '':
            phoneNum += '-' + groups[4]
        matches.append(phoneNum)
    
    for groups in emailRegex.findall(text):
        matches.append(groups[0])
    
    #将所有匹配连接成一个字符串,复制到剪贴板
    
    if len(matches) > 0:
        pyperclip.copy('\n'.join(matches))
        print('Copied to clipboard:')
        print('\n'.join(matches))
    else:
        print('No phone numbers or email address found.')
    

    相关文章

      网友评论

          本文标题:Python碎碎念(2):正则表达式

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