zoukankan      html  css  js  c++  java
  • 21. re模块

    一、正则

    1. 字符

    元字符 匹配内容
    . 匹配出换行外任意字符
    w 匹配字母或数字或下划线
    s 匹配任意空白符
    d 匹配数字
    匹配一个换行符
    匹配一个制表符
     匹配一个单词的结尾
    ^ 匹配指定字符的开始
    $ 匹配字符串的结尾
    W 匹配非字母数字下划线
    D 匹配非数字
    S 匹配非空白符
    a | b 匹配字符a或字符b
    () 匹配括号内的表达式,也是一个组
    [...] 匹配字符组中的字符
    [^...] 匹配除了字符组中的字符其他所有字符

    2. 量词

    量词 匹配内容
    * 重复0或更多次
    + 重复1或更多次
    重复0或1次
    {n} 重复n次
    {n, } 重复n或更多次
    {n, m} 重复n到m次

    3. 运用

    import re
    string_test = "hello"
    
    (1) .
    string_1 = re.findall('.', string_test)
    print(string_1)
    >['h', 'e', 'l', 'l', 'o']
    
    (2) ^
    string_2 = re.findall('^h', string_test)
    print(string_2)
    >['h']
    
    (3) $
    string_3 = re.findall('o$', string_test)
    print(string_3)
    >['o']
    
    (4) * - 当匹配单个字符的时候,会因为匹配0次而出现空字符
    string_test = "hello llo lw"
    string_1 = re.findall('l*', string_test)
    print(string_1)
    >['', '', 'll', '', '', 'll', '', '', 'l', '', '']
    
    string_test = "hello llo lw"
    string_1 = re.findall('ll*', string_test)
    print(string_1)
    >['ll', 'll', 'l']
    
    (5) + 
    string_test = "hello llo lw"
    string_1 = re.findall('l+', string_test)
    print(string_1)
    >['ll', 'll', 'l']
    
    string_test = "hello llo lw"
    string_1 = re.findall('ll+', string_test)
    print(string_1)
    >['ll', 'll']
    
    (6) ?
    string_test = "hello llo lw"
    string_1 = re.findall('l?', string_test)
    print(string_1)
    >['', '', 'l', 'l', '', '', 'l', 'l', '', '', 'l', '', '']
    
    string_test = "hello llo lw"
    string_1 = re.findall('ll?', string_test)
    print(string_1)
    >['ll', 'll', 'l']
    
    (7) {n, }
    str1='iii amiiii ssdii iihjf iiifgfdgi '
    str2=re.findall('ii{2,}',str1)
    print(str2)
    >['iii', 'iiii', 'iii']
    
    (8) {, m}
    str1='iii amiiii ssdii iihjf iiifgfdgi '
    str2=re.findall('ii{,2}',str1)
    print(str2)
    >['iii', 'iii', 'i', 'ii', 'ii', 'iii', 'i']
    
    (9) {n, m}
    str1='iii amiiii ssdii iihjf iiifgfdgi '
    str2=re.findall('ii{1,2}',str1)
    print(str2)
    >['iii', 'iii', 'ii', 'ii', 'iii']
    
    (10) d
    str1='iii amiiii 123er45vg44 '
    str2=re.findall(r'd',str1)
    print(str2)
    >['1', '2', '3', '4', '5', '4', '4']
    
    (11) w
    str1='iii am_你好iiii 123er45vg44 '
    str2=re.findall(r'w',str1)
    print(str2)
    >['i', 'i', 'i', 'a', 'm', '_', '你', '好', 'i', 'i', 'i', 'i', '1', '2', '3', 'e', 'r', '4', '5', 'v', 'g', '4', '4']
    
    (12) s
    str1='iii am_你好iiii 123
    er	45vg44 '
    str2=re.findall(r's',str1)
    print(str2)
    >[' ', ' ', '
    ', '	', ' ']
    
    (13) 
    str1='i love python '
    str2=re.findall(r'on',str1)
    str3=re.findall(r'on',str1)
    print(str2)
    print(str3)
    >[]
    >['on']
    
    (14) D
    str1='i love python12456'
    str2=re.findall(r'D',str1)
    print(str2)
    >['i', ' ', 'l', 'o', 'v', 'e', ' ', 'p', 'y', 't', 'h', 'o', 'n']
    
    (15) S
    str1='i love python12456
    	'
    str2=re.findall(r'S',str1)
    print(str2)
    >['i', 'l', 'o', 'v', 'e', 'p', 'y', 't', 'h', 'o', 'n', '1', '2', '4', '5', '6']
    
    (16) W
    str1='i love ¥%*python12456
    	'
    str2=re.findall(r'W',str1)
    print(str2)
    >[' ', ' ', '¥', '%', '*', '
    ', '	']
    
    (17) B
    str1='i love python12456'
    str2=re.findall(r'ovB',str1)
    print(str2)
    >['ov']
    
    (18) []字符集
    str1='i love python12456'
    str2=re.findall(r'[a-z]',str1)
    print(str2)
    >['i', 'l', 'o', 'v', 'e', 'p', 'y', 't', 'h', 'o', 'n']
    
    str1='i love python12456'
    str2=re.findall(r'[^d]',str1)
    print(str2)
    >['i', ' ', 'l', 'o', 'v', 'e', ' ', 'p', 'y', 't', 'h', 'o', 'n']
    
    (19) |
    str1='i love python12456
    
    '
    str2=re.findall(r'[d|s]',str1)
    print(str2)
    >[' ', ' ', '1', '2', '4', '5', '6', '
    ', '
    ']
    
    (20) () 分组-标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。只会匹配括号中的内容
    str1='i love python12456
    
    '
    str2=re.findall(r'n(d)',str1)
    print(str2)
    >['1']
    

    二、贪婪与非贪婪匹配

    ​ 正则表达式通常用于在文本中查找匹配的字符串。Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;非贪婪则相反,总是尝试匹配尽可能少的字符。在"*","?","+","{m,n}"后面加上?,使贪婪变成非贪婪。

    1. 贪婪模式

    ​ 贪婪模式下字符串查找会直接走到字符串结尾去匹配,如果不相等就向前寻找,这一过程称为回溯

    import re
    str1='<table><td><th>贪婪</th><th>贪婪</th><th>贪婪</th></td></table>贪婪'
    str2=re.findall(r'<.*>',str1)
    print(str2)
    
    >['<table><td><th>贪婪</th><th>贪婪</th><th>贪婪</th></td></table>']
    

    2. 非贪婪模式

    ​ 非贪婪模式下会自左向右查找,一个一个匹配不会出现回溯的情况

    import re
    str1='<table><td><th>贪婪</th><th>贪婪</th><th>贪婪</th></td></table>贪婪'
    str2=re.findall(r'<.*?>',str1)
    print(str2)
    >['<table>', '<td>', '<th>', '</th>', '<th>', '</th>', '<th>', '</th>', '</td>', '</table>']
    

    三、re模块使用

    1. re.A(re.ASCII)    
    	让w,W,,B,d,D,s和S 执行ASCII-只匹配完整的Unicode匹配代替。这仅对Unicode模式有意义,而对于字节模式则忽略。
        
    2. re.I(re.IGNORECASE)    
    	执行不区分大小写的匹配;类似的表达式也[A-Z]将匹配小写字母。
        
    3. re.L(re.LOCALE)  
    	让w,W,,B和区分大小写的匹配取决于当前的语言环境。该标志只能与字节模式一起使用。不建议使用此标志,因为语言环境机制非常不可靠,它一次只能处理一种“区域性”,并且仅适用于8位语言环境。默认情况下,Python 3中已为Unicode(str)模式启用了Unicode匹配,并且能够处理不同的语言环境/语言。
        
    4. re.M(re.MULTILINE)  
    	指定时,模式字符'^'在字符串的开头和每行的开头(紧随每个换行符之后)匹配;模式字符'$'在字符串的末尾和每行的末尾(紧接在每个换行符之前)匹配。默认情况下,'^' 仅在字符串的开头,字符串'$'的末尾和字符串末尾的换行符(如果有)之前立即匹配。
        
    5. re.S(re.DOTALL)    
    	使'.'特殊字符与任何字符都匹配,包括换行符;没有此标志,'.'将匹配除换行符以外的任何内容。
    

    1. findall(pattern, string, flags=0)

    ​ findall方法,该方法在字符串中查找模式匹配,将所有的匹配字符串以列表的形式返回,如果文本中没有任何字符串匹配模式,则返回一个空的列表,如果有一个子字符串匹配模式,则返回包含一个元素的列表,所以,无论怎么匹配,我们都可以直接遍历findall返回的结果而不会出错。

    import re
    
    re_str = "hello this is python 2.7.13 and python 3.4.5"
    pattern = "python [0-9].[0-9].[0-9]"
    result = re.findall(pattern=pattern, string=re_str)
    print(result)
    >['python 2.7.1', 'python 3.4.5']
    
    # 忽略大小写
    re_str = "hello this is python 2.7.13 and Python 3.4.5"
    pattern = "python [0-9].[0-9].[0-9]"
    result = re.findall(pattern=pattern, string=re_str, flags=re.IGNORECASE)
    print(result)
    >['python 2.7.1', 'Python 3.4.5']
    

    2. re.compile(pattern, flags=0)

    ​ 一般采用编译的方式使用python的正则模块,如果在大量的数据量中,编译的方式使用正则性能会提高很多

    import re
    
    re_str = "hello this is python 2.7.13 and Python 3.4.5"
    re_obj = re.compile(pattern = "python [0-9].[0-9].[0-9]",flags=re.IGNORECASE)
    res = re_obj.findall(re_str)
    print(res)
    >['python 2.7.1', 'Python 3.4.5']
    

    3. re.match(pattern, string, flags=0)

    ​ match方法,类似于字符串中的startwith方法,只是match应用在正则表达式中更加强大,更富有表现力,match函数用以匹配字符串的开始部分,如果模式匹配成功,返回一个SRE_Match类型的对象,如果模式匹配失败,则返回一个None,因此对于普通的前缀匹配

    1. 判断data字符串是否以what、数字开头
    
    import re
    
    s_true = "what is a boy"
    s_false = "What is a boy"
    re_obj = re.compile("what")
    print(re_obj.match(string=s_true))
    ><_sre.SRE_Match object; span=(0, 4), match='what'>
    print(re_obj.match(string=s_false))
    >None
    
    2. 匹配数字
    s_true = "123what is a boy"
    s_false = "what is a boy"
    re_obj = re.compile("d+")
    print(re_obj.match(s_true))
    ><_sre.SRE_Match object; span=(0, 3), match='123'>
    print(re_obj.match(s_true).start())
    >0
    print(re_obj.match(s_true).end())
    >3
    print(re_obj.match(s_true).string)
    >123what is a boy
    print(re_obj.match(s_true).group())
    >123
    print(re_obj.match(s_false))
    >None
    

    4. re.search(pattern, string, flag=0)

    ​ search方法,模式匹配成功后,也会返回一个SRE_Match对象,search方法和match的方法区别在于match只能从头开始匹配,而search可以从字符串的任意位置开始匹配,他们的共同点是,如果匹配成功,返回一个SRE_Match对象,如果匹配失败,返回一个None,这里还要注意,search仅仅查找第一次匹配,也就是说一个字符串中包含多个模式的匹配,也只会返回第一个匹配的结果,如果要返回所有的结果,最简单的方法就是findall方法,也可以使用finditer方法

    print(re.search('dcom','www.4comrunoob.5com').group())
    >4com
    
    *注:match和search一旦匹配成功,就是一个match object对象,而match object对象有以下方法:
    * group() 返回被 RE 匹配的字符串
    * start() 返回匹配开始的位置
    * end() 返回匹配结束的位置
    * span() 返回一个元组包含匹配 (开始,结束) 的位置
    * group() 返回re整体匹配的字符串,可以一次输入多个组号,对应组号匹配的字符串。
    
    import re
    
    a = "123abc456"
    print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0))   #123abc456,返回整体
    print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(1))   #123
    print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(2))   #abc
    print(re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(3))   #456
    >>>group(1) 列出第一个括号匹配部分,group(2) 列出第二个括号匹配部分,group(3) 列出第三个括号匹配部分
    

    5. re.finditer(pattern, string, flags=0)

    ​ 搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。找到 RE 匹配的所有子串,并把它们作为一个迭代器返回

    import re
    
    re_str = "what is a different between python 2.7.14 and python 3.5.4"
    re_obj = re.compile("d{1,}.d{1,}.d{1,}")
    
    for i in re_obj.finditer(re_str):
        print(i)
    >> <_sre.SRE_Match object; span=(35, 41), match='2.7.14'>
    >> <_sre.SRE_Match object; span=(53, 58), match='3.5.4'>
    

    6. re.sub(pattern, repl, string, count)

    ​ re模块sub方法类似于字符串中的replace方法,只是sub方法支持使用正则表达式

    import re
    
    re_str = "what is a different between python 2.7.14 and python 3.5.4"
    re_obj = re.compile("d{1,}.d{1,}.d{1,}")
    print(re_obj.sub("a.b.c",re_str,count=1))
    >what is a different between python a.b.c and python 3.5.4
    
    print(re_obj.sub("a.b.c",re_str,count=2))
    >what is a different between python a.b.c and python a.b.c
    
    print(re_obj.sub("a.b.c",re_str))
    >what is a different between python a.b.c and python a.b.c
    

    7、re.split(pattern, string[, maxsplit])

    re模块的split方法和python字符串中的split方法功能是一样的,都是将一个字符串拆分成子字符串的列表,区别在于re模块的split方法能够; maxsplit用于指定最大分割次数,不指定将全部分割
    
    print(re.split('d+','one1two2three3four4five5'))
    >['one', 'two', 'three', 'four', 'five', '']
    
  • 相关阅读:
    英特尔“硬盘内存一体化”首款产品正式发布,读写速度超千倍,存储密度扩充十倍
    程序员,你为什么值这么多钱?
    不懂程序看的明白《黑客帝国》吗?
    程序员的工作、学习与绩效
    架构设计师能力模型
    .net平台的MongoDB使用
    转载-30分钟搞定后台登录界面(103个后台PSD源文件、素材网站)
    XAF-DevExpress.ExpressApp.DC.Xpo.XpoTypeInfoSource 生成实体的过程-学习笔记
    谈谈敏捷开发
    XAF-由于try catch导致的性能问题一例
  • 原文地址:https://www.cnblogs.com/hq82/p/12457899.html
Copyright © 2011-2022 走看看