zoukankan      html  css  js  c++  java
  • Python知识点记录三(正则表达式)

    正则表达式

    正则表达式是一个特殊的字符序列,可以检测一个字符串是否与我们设定的字符序列相匹配。

    一、findall()方法

    re模块下的findall()方法可以查找对应字符/字符串

    最简单的方法可以查找字符串中的特定字符串:

    import re
    a = 'C|C++|Java|C#|Python|Javascript'
    
    r = re.findall('Python', a)   #返回一个包含结果的列表
    print(r)
    if len(r):
        print('字符串中包含Python。')
    else:
        print('字符串中不包含Python。')

    二、元字符和普通字符

    对于上例findall()方法中的第一个实参'Python'即为普通字符,即表示字符本意的字符。

    元字符:包括d匹配0-9中的数字;D匹配一个非数字字符,即[^0-9];等等。

    import re
    a = 'C0C++7Java8C#9Python6Javascrip'
    #通过'd'匹配数字字符
    r = re.findall('d',a)
    print(r)
    #通过'D'匹配数字字符
    r = re.findall('D',a)
    print(r)

    三、字符集

    正则表达式中通过字符集设定字符的可能值,字符集通过[]表示。

    如[0-9]表示0到9中的一个数字,即等同于元字符d;[cf]字符集匹配c或者f;a[hc]b匹配一个三个字符的字符串,第一个字符为a,第二个字符为h或c,第三个字符为b;[^1]匹配所有不是1的字符。

    import re
    
    s0 = 'He1ll2o,Wor3ld.'
    s1 = 'abc, acc1, adc, aec, a1efc, ahc'
    #匹配为e或o的字符
    r0 = re.findall('[eo]', s0)
    #匹配0-3之间的字符
    r00 = re.findall('[0-3]', s0)
    #匹配非小写字母的字符,且第二个字符为逗号
    r01 = re.findall('[^a-z],',s1)
    #匹配第一个字符为a,第三个字符为c,第二个字符为c或f的字符串
    r1 = re.findall('a[cf]c', s1)
    
    print(r0)
    print(r00)
    print(r01)
    print(r1)

    四、概括字符集

    上述提及的d等元字符可以理解为概况字符集,即概况描述某一类字符的集合,如d也可以表示为[0-9]字符集。

    元字符D可以用字符集[^0-9]表示;

    元字符w表示匹配单词字符(字母,数字,下划线)可以用字符集[A-Za-z0-9_]表示;

    元字符W表示匹配非单词字符,即%¥#@此类,也包括空格,制表符,回车,换行等空白字符;

    元字符s表示匹配空白字符,即空格、回车、换行符等。

    import re
    
    a = '_&python# 2java8
    9@php'
    #d匹配一个数字字符
    r = re.findall('d', a)
    #D匹配一个非数字字符
    r1 = re.findall('D', a)
    #w匹配一个单词字符(数字或字母字符或下划线)
    r2 = re.findall('w', a)
    #W匹配一个非单词字符
    r3 = re.findall('W', a)
    #s匹配一个空白字符
    r4 = re.findall('s', a)
    
    print(r)
    print(r1)
    print(r2)
    print(r3)
    print(r4)

    五、数量词

    对于以下代码:

    import re
    a = 'python 1111java678php'
    
    r = re.findall('[a-zA-Z]', a)
    print(r)
    
    #输出:['p', 'y', 't', 'h', 'o', 'n', 'j', 'a', 'v', 'a', 'p', 'h', 'p']

    因为参数正则表达式为一个字符集,仅匹配单个字符;如果需要以单词的形式作为输出的元素,则需要用到数量词这个方式。

    import re
    a = 'python 1111java678php'
    
    r = re.findall('[a-z]{3,6}', a)
    print(r)
    
    #输出:['python', 'java', 'php']

    参数中的[a-z]表示字符的匹配条件,{3,6}表示需要匹配的数量为3-6个,需要注意这里Python会默认采用贪婪的匹配方法,即如果已经匹配到3个字符后还会继续匹配,直到不再满足匹配条件,或达到匹配数量的最大值为止。

    import re
    a = 'python 1111java678php'
    
    r = re.findall('[a-z]{3,6}', a)
    print(r)
    
    #输出:['python', 'java', 'php']

    Python默认为贪婪匹配,如果要采用非贪婪模式匹配,则需要在数量词后加个'?':

    import re
    a = 'python 1111java678php'
    
    #非贪婪匹配方式
    r = re.findall('[a-z]{3,6}?', a)
    print(r)
    
    #输出:['pyt', 'hon', 'jav', 'php']

     *除了上述的'{}'表示数量词之外,也可以通过‘*’表示匹配星号前面字符0次或1次或无限次,通过'+'表示匹配加号前面字符至少1次,通过'?'表示匹配问号前面字符0次或1次。。

    import re
    
    a = 'pytho0python1pythonn2'
    #匹配*前面的n0次或1次或无限次
    r = re.findall('python*', a)
    #匹配+前面的n至少一次
    r1 = re.findall('python+', a)
    #匹配?前面的n0次或1次
    r2 = re.findall('python?', a)
    print(r)
    print(r1)
    print(r2)
    
    #输出:
    '''
    ['pytho', 'python', 'pythonn']
    ['python', 'pythonn']
    ['pytho', 'python', 'python']
    '''

    需要注意这里问号和前述数量词{}之后问号的区别。

    通过数量词实现上例,注意对比:

    import re
    
    a = 'pytho0python1pythonn2'
    #通过数量词{}取n1-2次,贪婪模式
    r = re.findall('python{1,2}', a)
    #通过数量词{}取n1-2次,非贪婪模式
    r1 = re.findall('python{1,2}?', a)
    
    print(r)
    print(r1)
    
    
    #输出:
    '''
    ['python', 'pythonn']
    ['python', 'python']
    '''

    六、边界匹配

    如果有一个数字字符串,需要判断是否为一个QQ号码,比如qq='10000001'。

    QQ号码的判断规则(假设)为4-8位的数字,如果单纯通过数量词查找:r = re.findall('d{4,8}', qq),对于本例也是可以查找匹配出的,但如果

    qq = '1234567890',通过前面的正则表达式'd{4,8}'也可以匹配到数字字符串,但显然这个QQ号码超出了8位,这里就需要通过边界匹配符来界定匹配范围:

    import re
    
    qq = '1234567890'
    #QQ号为4-8位,检测是否为QQ号码
    #通过边界匹配符'^...$'匹配整个字符串
    #第一个^表示从整个字符串开头匹配4-8个数字
    #最后一个$表示从整个字符串最末尾往前匹配4-8个数字
    #两者都匹配到的才为最终匹配到的结果
    r = re.findall('^d{4,8}$', qq)
    print(r)
    
        

    再单独理解一下边界匹配符的第一个^和最后一个$的作用:

    import re
    
    qq = '123a4567890abchf'
    #通过'^'匹配整个字符串开头的3-4个数字
    r0 = re.findall('^d{3,4}', qq)
    
    #通过'$'匹配整个字符串末尾的3-4个字母
    r1 = re.findall('[a-zA-Z]{3,4}$', qq)
    print(r0)
    print(r1)
    
    '''
    输出:
    ['123']
    ['bchf']
    '''
        

    七、组

    前面数量词的使用中数量词针对的是其前面的单个字符,也可以通过组的概念将整组字符适用到数量词上:

    import re
    
    a = 'PythonPythonPythonPythonJSJSPython'
    #找出是否含有连续三个Python,如果有则返回的是单个组,否则返回空列表
    r = re.findall('(Python){3}', a)
    #找出是否含有连续三个PYthon且连着两个JS
    r0 = re.findall('(Python){3}(JS){2}', a)
    #找出是否含有连续三个PYthon且连着三个JS
    r1 = re.findall('(Python){3}(JS){3}', a)
    print(r)
    print(r0)
    print(r1)
    
    
    '''
    输出:
    ['Python']
    [('Python', 'JS')]
    []
    '''

    八、匹配模式参数

    findall()还有第三个参数flags即指匹配模式,当参数值设为re.I则忽略正则表达式中的字母大小写;当参数值设为re.S则忽略

    import re
    language = 'PythonC#
    JavaPHP'
    #忽略大小写的模式
    r = re.findall('c#', language, re.I)
    #‘.’本来表示除了换行之外的所有字符,re.S模式表示'.'可以匹配任意字符
    #匹配整个字符串的最后两个字符
    r0 = re.findall('.{2}$', language, re.S)
    #匹配c#或C#及后面1-3个字符(非贪婪)
    r1 = re.findall('c#.{1,3}?', language, re.I | re.S)
    #匹配c#或C#及后面1-3个字符(贪婪)
    r1 = re.findall('c#.{1,3}', language, re.I | re.S)
    print(r)
    print(r0)
    print(r1)
    
    '''
    输出:
    ['C#']
    ['HP']
    ['C#
    Ja']
    '''

     九、sub()/match()/search()函数

    1、sub()函数可以实现查找后替换的功能。参数格式依此为正则表达式、需要匹配后替换的字符串(或函数)、原始字符串、匹配次数、模式参数。

    import re
    
    language = 'PythonC#JavaC#PHPC#'
    r = re.sub('C#', 'Javascript', language)
    print(r)
    
    #输出:PythonJavascriptJavaJavascriptPHPJavascript

    第四个参数表示匹配后替换的次数,默认为0,表示不限制次数的替换,如果设置为非0的某个数值,则表示替换的最大次数。

    import re
    
    language = 'PythonC#JavaC#PHPC#'
    #无限次替换
    r1 = re.sub('C#', 'Javascript', language, 0)
    #最多1次替换
    r2 = re.sub('C#', 'Javascript', language, 1)
    #最多2次替换
    r3 = re.sub('C#', 'Javascript', language, 2)
    #对比字符串内置函数replace()
    language0 = language.replace('C#', 'Javascript')
    print(r1)
    print(r2)
    print(r3)
    print(language0)
    
    '''
    输出:
    PythonJavascriptJavaJavascriptPHPJavascript
    PythonJavascriptJavaC#PHPC#
    PythonJavascriptJavaJavascriptPHPC#
    PythonJavascriptJavaJavascriptPHPJavascript
    '''

    第二个参数除了直接指定为字符串,也可以指定为某个函数,其功能是把正则匹配出的字符串作为该函数参数,返回的字符串作为替换的字符串。

    这里需要注意正则参数传递的时候实际是一个正则对象,需要通过访问其group()获得真正匹配到的字符串。

    import re
    
    def convert(value):
        v = value.group()
        return v+'!'
    
    language = 'PythonC#JavaC#PHPC#'
    
    r = re.sub('C#', convert, language)
    print(r)
    
    #输出:PythonC#!JavaC#!PHPC#!

    对于上例的convert()函数中,通过value.group()获取了匹配到的实际的字符串,这里value即是一个正则对象,除了group()函数,它还有span()方法,可以获取匹配到的字符串在原始字符串中的索引:

    import re
    
    def convert(value):
        #打印匹配到的字符在原始字符串中的索引
        print(value.span())
        v = value.group()
        return v + '!'
    
    language = 'PythonC#JavaC#PHPC#'
    
    r = re.sub('C#', convert, language)
    print(r)
    
    '''
    输出:
    (6, 8)  #匹配到的第一个C#对应索引为6,7
    (12, 14)#匹配到的第一个C#对应索引为12,13
    (17, 19)#匹配到的第一个C#对应索引为17,18
    PythonC#!JavaC#!PHPC#!
    '''
    import re
    
    s = 'A8C3721D86'
    
    #大于等于6的数字替换成9,其余数字替换为0
    def convert(value):
        n = int(value.group())
        if n >= 6:
            return '9'
        else:
            return '0'
    
    r = re.sub('d', convert, s)
    print(r)
    
    #输出:A9C0900D99
    import re
    
    s = 'A8C372R1X16D86F333P50F7N'
    
    #剔除所有的单个数字字符
    #两位数字大于50的替换为100,其余替换为0
    def convert(value):
        n = int(value.group())
        if n < 10:
            return ''
        elif n < 50:
            return '0'
        else:
            return '100'
    
    r = re.sub('d{1,10}', convert, s)
    print(r)
    
    #输出:AC100RX0D100F100P100FN

    2、search()/match()函数

    (1)match()尝试从字符串开头去匹配,匹配成功则返回第一个匹配的字符串,返回一个Match对象;如果没有匹配到则返回None。

    (2)search()将搜索整个字符串,直到找到第一个匹配的字符串,返回一个Match对象;如果没有匹配到则返回None。

    import re
    
    s = 'A8C3721D86'
    
    r = re.match('d', s)
    print(r)
    
    r0 = re.search('d', s)
    #通过对象的group()获取匹配到的字符串
    print(r0.group())

    需要特别注意的是:search()和match()函数只最多匹配一次,匹配到一次后不再继续查找匹配,而findall()函数会查找整个字符串范围。

    3、分组

    除了前述提到的数量重复的作用外,还可以通过分组括号指定需要匹配的字符:

    import re
    
    s = 'life is short,i use python,
     i love python'
    
    r = re.search('life(.*)python', s, re.S)
    #group()获取整个分组的匹配,即'life(.*)python'
    print(r.group())
    #也可以加下标0获取上述字符串
    print(r.group(0))
    #可以加下标1获取上述字符串中的小分组
    print(r.group(1))
    #groups()获取大分组下的小分组字符串,即上述(.*)
    print(r.groups())
    
    #通过findall()是最方便直观的:
    r1 = re.findall('life(.*)python', s, re.S)
    print(r1)
    print()
    import re
    
    s = 'life is short,i use python, i love python'
    #多个分组的情况
    r = re.search('life(.*)python(.*)python', s, re.S)
    #group()获取整个分组的匹配,即'life(.*)python(.*)python'
    print(r.group(0))
    #可以加下标1获取上述字符串中的第一个小分组
    print(r.group(1))
    #可以加下标2获取上述字符串中的第二个小分组
    print(r.group(2))
    #通过groups()获取小分组
    print(r.groups())
    
    #通过findall()是最方便直观的:
    r1 = re.findall('life(.*)python(.*)python', s, re.S)
    print(r1)
  • 相关阅读:
    数据库(MySQL):事务
    数据库(MySQL):存储引擎
    操作系统:虚拟存储器
    操作系统:内存管理
    操作系统:进程与线程
    近期目标
    计算机网络:TCP三次握手、四次挥手
    计算机网络:OSI与TCP/IP各层的结构与功能,都有哪些协议
    计算机网络:从输入URL到页面加载
    Java:JVM
  • 原文地址:https://www.cnblogs.com/tsembrace/p/9011686.html
Copyright © 2011-2022 走看看