zoukankan      html  css  js  c++  java
  • 17.正则表达式

    正则表达式

    1.什么是正则表达式

    """
    定义:
        用来约束字符串匹配某种形式的规则
    作用;
        1.检测某个字符串是否符合规则;(手机号,身份证号是否合法)
        2.提取网页字符串中想要的数据.(爬虫中提取天气,幸运的信息)
        在线测试工具  http://tool.chinaz.com/regex/
    组成: 普通字符和元字符组成
        1.普通字符串: 大小写字母和数字
        2.元字符具有特殊含义,大体种类分为:
            (1)预定义字符集,字符组
            (2)量词
            (3)边界符
            (4)分组   
    函数:需要导入import re 模块
    	findall("正则表达式","字符串") 从左到右匹配,找到所有的内容,返回列表
    	search("正则表达式","字符串")  从左到右匹配,匹配到第一个满足条件的内容直接返回,返回的是对象
    """
    
    

    2.匹配单个字符 : 预定义字符集和字符组

    import re
    
    """
    语法:re.findall("正则表达式","字符串") 返回列表
    注意:正则表达式前面加r防止转义,一定不会错
    """
    # 1.预定义字符集
    # . 匹配任意字符,除了换行符
    
    print(re.findall(".","3a
    d"))  #['3', 'a', '
    ', 'd']
    
    # d 匹配数字
    # D 匹配非数字
    print(re.findall("d","sd3kj4")) #['3', '4']
    print(re.findall("D","sd3kj4")) #['s', 'd', 'k', 'j']
    
    # w 匹配字母数字下划线和中文
    # W 匹配非字母数字下划线和中文
    print(re.findall("w","f2_健康*&")) #['f', '2', '_', '健', '康']
    print(re.findall("W","f2_健康*&")) #['*', '&']
    
    # s 匹配任意的空白符(空格,
    ,	,
     等)
    # S 匹配任意非空白符
    print(re.findall("s","k d 
    d")) #[' ', ' ', '
    ']
    print(re.findall("S","k d 
    d")) #['k', 'd', 'd']
    
    # 
     匹配换行符
    # 	 匹配制表符
    strvar = """
    11122			3434
    """
    print(re.findall(r"
    ",strvar)) #['
    ', '
    ']
    print(re.findall(r"	",strvar)) #['	', '	', '	']
    
    # 2.字符组 默认必须从字符组中选一个
    """
    [...]  匹配字符组中的字符
    [^..] 匹配非字符组中的字符(^必须写在第一位)
    [0-9] 表示 0~9 所有数字
    [a-z] 表示所有小写字母
    [A-Z] 表示所有大写字母
    [0-9a-zA-Z] 表示所有字母数字,该正则可验证十六进制 
    [u4e00-u9fa5] 表示匹配所有汉字
    """
    print(re.findall("[12]","d2k43jl1")) #['2', '1']
    print(re.findall('a[0-9]b','a1b a2b a3b acb ayb')) #['a1b', 'a2b', 'a3b']
    print(re.findall('a[0-9][*#/]b','a1/b a2b a29b '))#['a1/b']
    
    # 3.匹配转义字符
    """
    需要()进行转义
    而且正则表达式和后面字符串都需要加r
    """
    # (1)匹配^ -  特殊字符 
    strvar1 = "a^n a-n a
    " 
    strvar2 = r"a^n a-n a
    "  #加r防止转义
    print(re.findall(r"a[^-\]n",strvar1)) #['a^n', 'a-n']
    print(re.findall(r"a[^-\]n",strvar2)) #['a^n', 'a-n', 'a\n']
    
    # (2)匹配
    strvar=r"aedkja lka"
    print(re.findall(r"a\b",strvar))#['a\b', 'a\b']
    
    

    3.多个字符匹配 : 量词

    # 1.量词
    """
    ? : 匹配 0~1 个
    +: 匹配 1~+∞ 个
    * : 匹配 0~+∞ 即任意个
    {n} 匹配n 个
    {n,m} 匹配 n~m 个
    {n,} 匹配 n~+∞
    """
    print(re.findall("a?b","baabab abb")) #['b', 'ab', 'ab', 'ab', 'b']
    print(re.findall("a+b","baabab abb")) #['aab', 'ab', 'ab']
    print(re.findall("a*b","baabab abb")) #['b', 'aab', 'ab', 'ab', 'b']
    print(re.findall("a{2}b","baabab abb")) #['aab']
    print(re.findall("a{1,3}b","baabab abb")) #['aab', 'ab', 'ab']
    print(re.findall("a{1,}b","baabab abb")) #['aab', 'ab', 'ab']
    
    # 2.贪婪匹配和非贪婪匹配
    """
    贪婪模式 :默认向更多次匹配
        回溯算法 : 从左向右一直匹配,直到匹配不到了,在回头,把上一次找到的元素返回
    非贪婪模式: 默认向更少次匹配
        语法:量词 + "?"
        例:.*?w  表示匹配任意长度任意字符遇到一个w就立即停止
    """
    strvar="刘能和刘老根和刘一手1子2子"
    print(re.findall("刘.?",strvar)) #['刘能', '刘老', '刘一']
    print(re.findall("刘.??",strvar))#['刘', '刘', '刘']
    print(re.findall("刘.+",strvar)) #['刘能和刘老根和刘一手1子2子']
    print(re.findall("刘.+?",strvar))#['刘能', '刘老', '刘一']
    print(re.findall("刘.*子",strvar)) #['刘能和刘老根和刘一手1子2子']
    print(re.findall("刘.*?子",strvar))#['刘能和刘老根和刘一手1子']
    
    # 3.匹配开头结尾->边界符
    """
    只要不是字母数字下划线都可以作为边界
    边界符 : 
        1. 可以作为转义字符 ->退格
        2. 正则中的边界符
        例如:word  卡住左边界w ,卡主右边界 d
        注意:正则表达式前需要加r 防止转义
        
    ^ :匹配字符串的开始
    $ :匹配字符串的结尾
        如果使用了^ 和 $ 必须要把字符串看成一个整体
    """
    strvar = "word pwd wook"
    # 卡住左边界
    print(re.findall(r"w",strvar))#['w', 'w']
    print(re.findall(r"p",strvar))#['p']
    print(re.findall(r"w.*",strvar))#['word pwd wook']
    print(re.findall(r"w.*?",strvar))#['w', 'w']
    print(re.findall(r"wS*",strvar))#['word', 'wook']
    
    # 卡主右边界
    print(re.findall(r"d",strvar))#['d', 'd']
    print(re.findall(r".*d",strvar))#['word pwd']
    print(re.findall(r".*?d",strvar))#['word', ' pwd']
    
    # ^ 匹配字符串的开始  $匹配字符串的结尾
    print(re.findall("^w.*",strvar))#['word pwd wook']
    print(re.findall("^w.*?",strvar))#['w']
    print(re.findall("k$",strvar)) #['k']
    print(re.findall(".*k$",strvar))#['word pwd wook']
    print(re.findall(".*?k$",strvar))#['word pwd wook']从左到右匹配,结尾结束
    
    

    4.匹配分组

    import re
    
    # 1.匹配分组()表示一个整体
    """
    (正则表达式):优先显示括号里的内容
    (?:正则表达式):取消优先显示
    """
    print(re.findall(".*?_d","jia_d ying_d he_d")) #['jia_d', ' ying_d', ' he_d']
    print(re.findall("(.*?)_d","jia_d ying_d he_d"))#['jia', ' ying', ' he']
    print(re.findall("(?:.*?)_d","jia_d ying_d he_d"))#['jia_d', ' ying_d', ' he_d']
    
    # 2.| 或
    """
    注意:
        把较难匹配的内容放到前面,容易匹配的放到后面,才能保证所有元素都可以匹配到
    """
    print(re.findall("ab|abc","sabcdfabdabc"))#['ab', 'ab', 'ab']
    print(re.findall("abc|ab","sabcdfabdabc"))#['abc', 'ab', 'abc']
    
    strvar="2.3 22 33. ..44 66.66 77"
    # 匹配小数
    print(re.findall("d+.d+",strvar))#['2.3', '66.66']
    # 匹配整数(取值不正确)
    print(re.findall("d+",strvar)) #['2', '3', '22', '33', '44', '66', '66', '77']
    # 匹配小数和整数
    print(re.findall("d+.d+|d+",strvar))#['2.3', '22', '33', '44', '66.66', '77']
    # 使用分组的形式匹配小数和整数
    print(re.findall("d+(?:.d+)?",strvar))#['2.3', '22', '33', '44', '66.66', '77']
    
    # 匹配135或137的手机号
    strvar="13546346454 13640393839 13728394583"
    print(re.findall("(?:135|137)d{8}",strvar))#['13546346454', '13728394583']
    # 只匹配一个手机号
    strvar="13593849384"
    print(re.findall("^(?:135|137)d{8}$",strvar))#['13593849384']
    
    # 匹配www.baidu.com 或者 www.oldboy.com
    strvar = "www.baidu.com  www.oldboy.com  www.bxbxww.com"
    lst = re.findall("(?:www).(?:baidu|oldboy).(?:com)",strvar)
    print(lst)  #['www.baidu.com', 'www.oldboy.com']
    
    # 3.反向引用:
    引用前面第n个分组匹配到的内容
    strvar="<abs>dk3<abs>"
    # 把第一个括号里面的数据放到1引用
    obj=re.search(r"<(.*?)>(.*?)<1>",strvar)
    print(obj.group())#获取匹配到的数据
    print(obj.groups())#获取分组里面的内容
    
    #4.命名分组
    """
    (?P<组名>正则表达式) 给分组起一个名字
    (?P=组名) 引用组名,把该组名匹配到的数据放到当前位置
    """
    obj=re.search(r"<(?P<tag1>.*?)>(?P<tag2>.*?)<(?P=tag1)>",strvar)
    print(obj.group()) #<abs>dk3<abs>
    print(obj.groups()) #('abs', 'dk3')
    
    # 4.search函数和findall的区别
    """
    findall  :  优点:从左到右匹配,找到所有的内容,返回列表
    			缺点:匹配的内容和分组的内容不能同时显示在同一个界面中
    			
    search   :  缺点:从左到右匹配,匹配到第一个满足条件的内容直接返回,返回的是对象
    			优点:可以把分组里的内容和匹配到的内容同时显示在同一个界面中
    
    obj.group()  => 获取匹配到的内容
    obj.groups() => 获取分组中的内容
    """
    obj=re.search("(www).(baidu|oldboy).(com)",strvar)
    print(obj)  #返回对象
    print(obj.group()) #www.baidu.com
    print(obj.groups()) #('www', 'baidu', 'com')
    
    

    5.正则函数

    # 1.findall 匹配字符串相应内容, 返回列表
    """
    findall ("正则表达式","字符串")
    """
    strvar="sdf23sd"
    print(re.findall("d",strvar)) #['2', '3']
    
    # 2.search 匹配出第一个符合条件的数据返回,返回对象
    obj=re.search("d",strvar)
    print(obj.group()) #2
    
    # 3.match 验证用户输入内容
    """
    与search使用方法一样,search正则表达式开头加^(以..开头),等价于match
    """
    
    # 4.split ("正则表达式","字符串") 按正则表达式把字符串切割成列表
    strvar="aa|bb&cc*dd_ee"
    print(re.split("[|&*_]",strvar))#['aa', 'bb', 'cc', 'dd', 'ee']
    strvar="aa343bb33214cc"
    print(re.split("d+",strvar)) #['aa', 'bb', 'cc']
    
    # 5.sub 替换 返回被替换的字符串
    """
    sub("正则表达式","替换的元素","原字符串",替换次数)
    """
    strvar="aa|bb&cc*dd_ee"
    print(re.sub("[|*&_]","@",strvar)) #aa@bb@cc@dd@ee
    print(re.sub("[|*&_]","@",strvar,2)) #aa@bb@cc*dd_ee
    
    # 6.subn 替换  与sub一样 返回元组
    """
    sub("正则表达式","替换的元素","原字符串",替换次数)
    返回 : ("被替换的字符串",替换次数)
    """
    print(re.subn("[|*&_]","@",strvar,2)) #('aa@bb@cc*dd_ee', 2)
    
    # 7.finditer 匹配字符串中相应内容,返回迭代器
    strvar="s234sf"
    it=re.finditer("d",strvar)
    print(it) #<callable_iterator object at 0x7f21f3c536a0>
    print(next(it)) #<_sre.SRE_Match object; span=(1, 2), match='2'>
    """迭代器里面是类似search对象,需要用group获取内容"""
    print(next(it).group()) #3
    it=re.finditer("d",strvar) #重置迭代器
    for i in it:
        print(i.group())
    
    # 8.compile ("正则表达式")制定一个统一的匹配规则
    """
    compile("正则表达式",flags=修饰符) flags默认为0
    修饰符:
        1.re.I(大写i)    使匹配对大小写不敏感
        2.re.M  使每一行都能够单独匹配(多行匹配),影响^和$
        3.re.S    使 . 匹配包括换行在内的所有字符
    作用:制定一次正则表达式,重复使用,提高执行效率
    """
    pattern=re.compile("d") #制定匹配规则
    print(pattern) #re.compile('\d')
    # 使用规则
    strvar="ad334j"
    print(pattern.findall(strvar)) #['3', '3', '4']
    obj=pattern.search(strvar)
    print(obj.group()) #3
    
    # 修饰符
    # 1.re.I    使匹配对大小写不敏感
    strvar="<a>都会尽快</A>"
    pattern=re.compile("<a>(.*?)</a>",flags=re.I)
    obj=pattern.search(strvar)
    print(obj.group())
    
    # 2.re.M  使每一行都能够单独匹配,影响^和$
    strvar = """
    <a>我是连接</a>
    <p>我是段落</p>
    <div>我是盒子</div>
    """
    pattern=re.compile("^<.*?>.*?<.*?>$",flags=re.M)
    print(pattern.findall(strvar))#['<a>我是连接</a>', '<p>我是段落</p>', '<div>我是盒子</div>']
    
    # 3.re.S    使 . 匹配包括换行在内的所有字符
    strvar="""
    dskfl jdfks
    fdj3423me
    """
    pattern=re.compile(".*?me",flags=re.S)
    obj=pattern.search(strvar)
    print(obj.group()) #字符串所有内容,包括换行
    
    # 想要所有修饰符,使用|进行拼接
    pattern=re.compile(".*?me",flags=re.I|re.M|re.S)
    
    
  • 相关阅读:
    mysql 5.7修改密码
    使用zfs进行pg的pitr恢复测试
    什么是构造函数?它和普通函数的区别?
    匿名函数和普通函数的区别
    http缓存机制
    全局变量和局部变量
    什么是web语义化?
    ajax状态值和状态码
    如何理解MVVM?
    如果理解&&运算符和各类数值的布尔值
  • 原文地址:https://www.cnblogs.com/jia-shu/p/14129893.html
Copyright © 2011-2022 走看看