美文网首页
Python学习(十三)--正则表达式

Python学习(十三)--正则表达式

作者: 白面葫芦娃92 | 来源:发表于2020-08-06 11:29 被阅读0次

    1.概述

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

    主要用于快速检索文本、实现一些替换文本的操作
    例如:
    (1)检查一串数字是否是电话号码
    (2)检查一个字符串是否符合email
    (3)把一个文本里指定的单词替换为另一个单词

    2.初识

    不使用正则表达式查找字符串中某个单词

        a = 'C|C++|Java|Python|C#|Javascript'
        print(a.index('Python') > -1)
        print('Python' in a)
    ==>
        True
        True
    

    使用正则表达式:要用到Python的模块re

    import re
    
    a = 'C|C++|Java|Python|C#|Javascript'
    r = re.findall('Python',a)
    print(r)
    if len(r) > 0:
        print('字符串中包含Python')
    else:
        print('No')
    ==>
    ['Python']
    字符串中包含Python
    

    3.数字正则表达式

    b = 'C0C++7Java8Python9C#6Javascript'
    需求:找出字符串中所有的数字
    (1)方法1:for in 循环找出所有的数字
    (2)方法2:

    import re
    
    b = 'C0C++7Java8Python9C#6Javascript'
    re.findall('0' , b)
    re.findall('1' , b)
    re.findall('2' , b)
    re.findall('3' , b)
    .....
    re.findall('9' , b)
    

    (3)方法3:

    import re
    
    b = 'C0C++7Java8Python9C#6Javascript'
    r = re.findall('\d' , b)    #\d表示所有的数字
    print(r)
    ==>
    ['0', '7', '8', '9', '6']
    

    4.正则表达式类型

    (1)普通字符 'Python'
    (2)元字符
    例如:'\d' 匹配一个数字字符。等价于[0-9]
    '\D' 匹配一个非数字字符。等价于[^0-9]
    (3)普通字符和元字符混合
    参考链接:https://baike.baidu.com/item/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F
    https://www.runoob.com/regexp/regexp-metachar.html

    5.字符集

    import re
    
    s = 'abc, acc, adc, aec, afc, ahc'
    #找出所有中间字母为c或者f的单词
    r = re.findall('a[cf]c', s)
    print(r)
    #找出所有中间字符非c或f或d的单词
    r1 = re.findall('a[^cdf]c',s)
    print(r1)
    #找出所有中间字符为c或d或e或f的单词
    r2 = re.findall('a[c-f]c',s)
    print(r2)
    ==>
    ['acc', 'afc']
    ['abc', 'aec', 'ahc']
    ['acc', 'adc', 'aec', 'afc']
    

    6.概括字符集

    '\d' 匹配一个数字字符。等价于[0-9]
    '\D' 匹配一个非数字字符。等价于[^0-9]
    [\w] 匹配包括下划线的任何单词字符。类似但不等价于“[A-Za-z0-9_]”,这里的"单词"字符使用Unicode字符集,例如 & 是匹配不到的
    [\W] 匹配任何非单词字符。等价于[^A-Za-z0-9_] 包含空格、回车、制表符等
    [\s] 匹配任何不可见字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]
    [\S] 匹配任何可见字符。等价于[^ \f\n\r\t\v]
    .点 匹配除“\n”和"\r"之外的任何单个字符。要匹配包括“\n”和"\r"在内的任何字符,请使用像“[\s\S]”的模式

    a = 'C#\rpython_11&11 java\n678\tphp'
    r1 = re.findall('[0-9]',a)
    print(r1)
    r2 = re.findall('[^0-9]',a)
    print(r2)
    r3 = re.findall('\w',a)
    print(r3)
    r4 = re.findall('\W',a)
    print(r4)
    r5 = re.findall('\s',a)
    print(r5)
    r6 = re.findall('\S',a)
    print(r6)
    r7 = re.findall('.',a)
    print(r7)
    ==>
    ['1', '1', '1', '1', '6', '7', '8']
    ['C', '#', '\r', 'p', 'y', 't', 'h', 'o', 'n', '_', '&', ' ', 'j', 'a', 'v', 'a', '\n', '\t', 'p', 'h', 'p']
    ['C', 'p', 'y', 't', 'h', 'o', 'n', '_', '1', '1', '1', '1', 'j', 'a', 'v', 'a', '6', '7', '8', 'p', 'h', 'p']
    ['#', '\r', '&', ' ', '\n', '\t']
    ['\r', ' ', '\n', '\t']
    ['C', '#', 'p', 'y', 't', 'h', 'o', 'n', '_', '1', '1', '&', '1', '1', 'j', 'a', 'v', 'a', '6', '7', '8', 'p', 'h', 'p']
    ['C', '#', '\r', 'p', 'y', 't', 'h', 'o', 'n', '_', '1', '1', '&', '1', '1', ' ', 'j', 'a', 'v', 'a', '6', '7', '8', '\t', 'p', 'h', 'p']
    

    7.数量词

    (1)?
    当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少地匹配所搜索的字符串,而默认的贪婪模式则尽可能多地匹配所搜索的字符串。例如,对于字符串“oooo”,“o+”将尽可能多地匹配“o”,得到结果[“oooo”],而“o+?”将尽可能少地匹配“o”,得到结果 ['o', 'o', 'o', 'o']

    贪婪:尽可能匹配最大设置数量来做匹配,尽可能匹配更多,满足3时,不会立刻满足并返回结果,还会继续往下匹配,因此会匹配出python
    例如:[a-z]{3,6} 会尽可能按照[a-z]{6}做匹配
    非贪婪:[a-z]{3,6}? 一旦满足3,就返回结果了

    import re
    
    a = 'ptho0python1pythonn2'
    
    r = re.findall('[a-z]{3,6}',a)
    print(r)
    
    r1 = re.findall('[a-z]{3,6}?',a)
    print(r1)
    ==>
    ['ptho', 'python', 'python']
    ['pth', 'pyt', 'hon', 'pyt', 'hon']
    

    (2)*
    匹配前面的子表达式任意次。例如,zo能匹配“z”,也能匹配“zo”以及“zoo”。等价于{0,}

    import re
    
    a = 'pytho0python1pythonn2'
    r3 = re.findall('python*',a)
    print(r3)
    ==>
    ['pytho', 'python', 'pythonn']
    

    (3)+
    匹配前面的子表达式一次或多次(大于等于1次)。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}

    import re
    
    a = 'pytho0python1pythonn2'
    r3 = re.findall('python+',a)
    print(r3)
    ==>
    ['python', 'pythonn']
    

    (4)?
    匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“do”或“does”。?等价于{0,1}

    import re
    
    a = 'pytho0python1pythonn2'
    r3 = re.findall('python?',a)
    print(r3)
    ==>
    ['pytho', 'python', 'python']
    

    8.边界匹配

    qq = '100001'
    需求:校验QQ号是否合规,要求QQ号必须在4-8位之间
    错误方法:

    r = re.findall('\d{4,8}',qq)
    #qq号小于4位时,能筛选出错误的qq号
    #当qq = '1000000001'  为9位时,上方语句也能匹配出来,这样就错了
    

    正确方法:

    #从行首开始匹配,满足4-8字符,同时后边紧跟着行尾
    r = re.findall('^\d{4,8}$',qq)
    

    ^:匹配输入字行首。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置
    $:匹配输入行尾。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置

    qq = '100001'
    r1 = re.findall('^000',qq)
    print(r1)
    r2 = re.findall('000$',qq)
    print(r2)
    ==>
    []
    []
    

    9.以单词为最小单位匹配,用()括起来即可

    a = 'PythonPythonPythoPythonPythonPython'
    #匹配是否有连续3个Python
    r = re.findall('(Python){3}',a)
    print(r)
    r1 = re.findall('(Python){4}',a)
    print(r1)
    ==>
    ['Python']
    []
    

    10.匹配模式

    language = 'PythonC#\nJavaPHP'
    r = re.findall('c#',language)
    print(r)
    ==>
    []
    #匹配不到
    
    修饰符 描述
    re.I 使匹配对大小写不敏感
    re.S 使 . 匹配包括换行在内的所有字符
    re.L 做本地化识别(locale-aware)匹配
    re.M 多行匹配,影响 ^ 和 $
    re.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
    re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。

    使用re.I使匹配对大小写不敏感

    language = 'PythonC#\nJavaPHP'
    r = re.findall('c#',language,re.I)
    print(r)
    ==>
    ['C#']
    

    需求:匹配到c#和其后边的一个换行符

    language = 'PythonC#\nJavaPHP'
    r = re.findall('c#.{1}',language,re.I)
    ==>
    []
    #匹配不到,因为.点无法匹配“\n”和“\r”这种字符
    

    使用re.S使 . 匹配包括换行在内的所有字符

    language = 'PythonC#\nJavaPHP'
    r = re.findall('c#.{1}',language,re.I | re.S)
    print(r)
    ==>
    ['C#\n']
    

    11.re.sub 正则替换

    import re
    
    language = 'PythonC#JavaC#PHPC#'
    r = re.sub('C#','GO',language)
    #上述语句等同于r = re.sub('C#','GO',language,0),意思是字符串的C#全部替换
    print(r)
    ==>
    PythonGOJavaGOPHPGO
    

    可以选择不全部替换'C#'

    language = 'PythonC#JavaC#PHPC#'
    r = re.sub('C#','GO',language,1)
    print(r)
    ==>
    PythonGOJavaC#PHPC#
    
    language = 'PythonC#JavaC#PHPC#'
    r = re.sub('C#','GO',language,2)
    print(r)
    ==>
    PythonGOJavaGOPHPC#
    

    全部替换也可以用另一个函数:replace

    language = language.replace('C#','GO')
    print(language)
    ==>
    PythonGOJavaGOPHPGO
    

    sub函数的第二个参数不仅可以是一个常量,也可以是一个函数
    例如:

    import re
        
    def convert(value):
        pass
    language = 'PythonC#JavaC#PHPC#'
    r = re.sub('C#',convert,language)
    print(r)
    ==>
    PythonJavaPHP
    

    源字符串如果有'C#',则'C#'会作为函数convert的入参,convert的输出则将替换'C#',上方因为convert输出为空,因此所有'C#'消失了
    打印一下函数convert的入参value

    def convert(value):
        print(value)
    ==>
    <re.Match object; span=(6, 8), match='C#'>
    <re.Match object; span=(12, 14), match='C#'>
    <re.Match object; span=(17, 19), match='C#'>
    

    原来value不单纯只是一个字符串,而是一个对象,那么怎么直接拿到对象的内容?使用group()函数

    def convert(value):
        matched = value.group()
        return '!!'+ matched + '!!'
    language = 'PythonC#JavaC#PHPC#'
    r = re.sub('C#',convert,language)
    print(r)
    ==>
    Python!!C#!!Java!!C#!!PHP!!C#!!
    

    12.练习

    字符串s = 'A83C27D1D8E67'
    按如下规则进行字符串转换:
    (1)找到所有数字,数字为1位则删掉
    (2)数字为2位,则判断数字是否大于等于50,若是,则替换为99;若不是,则替换为00
    答案:

    s = 'A83C27D1D8E67'
    def convert(value):
        matched = value.group()
        if len(matched) < 2:
            return ''
        elif int(matched) >= 50:
            return '99'
        else:
            return '00'
    r = re.sub('\d{1,2}',convert,s)
    print(r)
    ==>
    A99C00DDE99
    

    13.match和search

    s = 'A83CF8943GH44'
    #match从字符串的第一个字符开始匹配,匹配不到\d就返回None
    r1 = re.match('\d',s)
    print(r1)
    #search从整个字符串进行搜索,当搜索到第一个符合条件的字符时就返回该字符,并停止搜索
    r2 = re.search('\d',s)
    print(r2)
    ==>
    None
    <re.Match object; span=(1, 2), match='8'>
    

    14.group()

    import re
    
    s = 'life is short,i use python'
    s1 = 'life is short,i use python,i love python'
    
    r = re.findall('life(.*)python',s)
    print(r)
    
    r = re.search('life(.*)python(.*)python',s1)
    print(r.group(0))
    print(r.group(1))
    print(r.group(2))
    print(r.groups())
    ==>
    [' is short,i use ']      # 用圆括号括起来,可以不输出边界,只输出想要的部分
    life is short,i use python,i love python      #group(0)默认输出全部
     is short,i use      #group(1)输出第一个圆括号中的内容
    ,i love      #group(2)输出第二个圆括号中的内容
    (' is short,i use ', ',i love ')      #groups()把两个括号中的内容合成一个元组输出
    

    15.JSON是一种轻量级的数据交换格式

    (1)和XML相比,JSON很轻量
    字符串是JSON的表现形式
    符合JSON格式的字符串,就是JSON字符串
    JSON是跨语言的,在每一种语言基本都能找到相对应的数据格式

    import json
    
    json_str = '{"name":"huluwa", "age":18}'
    json_str1 = '[{"name":"huluwa", "age":18, "flag":false},{"name":"test", "age":28}]'
    # 注意点:
    # 1.key一定要用双引号引起来,单引号不行(与语言无关)
    # 2.字符串一定要用双引号引起来,单引号不行(与语言无关),数字不需要引起来
    # 3.python内部有双引号,最外部一定要用单引号(与python有关)
    student = json.loads(json_str)
    print(type(student))
    print(student)
    
    student1 = json.loads(json_str1)
    print(type(student1))
    print(student1)
    
    ==>
    <class 'dict'>
    {'name': 'huluwa', 'age': 18}
    <class 'list'>
    [{'name': 'huluwa', 'age': 18, 'flag': False}, {'name': 'test', 'age': 28}]
    

    (2)反序列化

    # 从字符串转化成语言下的某种数据类型的过程,叫做反序列化,反之则叫做序列化;
    # json.loads()就是一个反序列化的过程,下面来看一下序列化:
    
    student2 = [
        {'name':'huluwa','age':18,'flag':False},
        {'name':'test','age':28}
    ]
    
    print(type(student2))
    json_str2 = json.dumps(student2)
    print(type(json_str2))
    print(json_str2)
    ==>
    <class 'list'>      #student2本来是list类型
    <class 'str'>      #经过json.dumps()之后变成了字符串类型
    [{"name": "huluwa", "age": 18, "flag": false}, {"name": "test", "age": 28}]
    

    (3)JSON和python数据类型对应列表

    JSON python
    object dict
    array list
    string str
    number int
    number float
    true True
    false False
    null None

    相关文章

      网友评论

          本文标题:Python学习(十三)--正则表达式

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