正则表达式:(re库)

import re

正则表达式是如何进行比对的?
1.遍历目标字符串
2.依次取出单个字符与表达式中的第一个规则字符进行匹配
    如果一致,则遍历下一个字符与规则字符串中的第二个进行匹配,重复如此操作;如果都匹配上了则从目标字符串中取出该结果,放置到列表;
    接着从上一个匹配成功的位置作为起始点继续往下找(注意:不会往前找了),如果找到则再次添加到列表;
3. 例如:
    print(re.findall('str','8string str'))
    >> ['str', 'str']
实际考核是否理解: 
    print(re.findall('a.b','abb a\nb abb'))
                                a.b   # .号不能匹配换行符,匹配失败;则下一次应该是a与\n开始比对,因为最开始是与a作为起始比对,没有对上
                                  a.b
"""

"""正则表达式匹配单个字符
1. 匹配单个字符
\w: 匹配字母数字下划线
    print(re.findall('str','8string str'))
    >> ['s', 't', 'r', 'i', 'n', 'g', 's', 't', 'r', '_', '3']  # 可以看到,没有匹配空格
    
\W: 取反,匹配非字符数字下划线
    print(re.findall(r'\W','${get'))
    >> ['$', '{']
    
\s: 匹配任意空白字符,等价于[\t\n\r\f],以及空格;ps:\r是回车,\f是换页;\s就是拿\n\t等这些空白的字符去一个个匹配;
    print(re.findall(r'\s','\nstring name\t\r\f'))
    >> ['\n', ' ', '\t', '\r', '\x0c']  # ps:如果字符串变成原始字符串,不会匹配到,如r'\nstring name\t\r\f'
    
\S: 取反,匹配非空白字符
    print(re.findall(r'\S','${g e t\n'))
    >> ['$', '{', 'g', 'e', 't'] 
    
\d: 匹配任意数字,相当于[0-9]
    print(re.findall(r'\d','${get(age=6,name="7")}'))
    >> ['6', '7']
    
\D: 取反,匹配非数字
    print(re.findall(r'\D', 'abcdef1234'))
    >> ['a', 'b', 'c', 'd', 'e', 'f']
    
-------------------------------------------------------------------------
\A: 只匹配开头的字符串,中间如果也有符合条件的,不会去匹配,匹配不到就是空列表
    print(re.findall(r'\A李白', '李白是李白'))
    >> ['李白']
    
\Z:只匹配结尾符合条件的字符串,中间如果也有符合条件的,不会去匹配,,匹配不到就是空列表
    print(re.findall(r'\A是', '是李白是'))
    >> ['是']
    注意:如果字符有过换行,是匹配不到的,只有字符串是一行的情况下才能匹配到
    print(re.findall(r'\A是', \"""
    是李白是
    \"""))
    
上面这种方式了解即可,我们实际上匹配时用的是^$;$就可解决上面的问题;
^: 匹配开头
$: 匹配结尾
    联用
    print(re.findall(r'^ales$','ales')) # 注意^别放到了字符串的后面a^
    >> ['ales']
    print(re.findall(r'^ales$','al  es'))
    >> []
-------------------------------------------------------------------------

. 匹配任意字符,除了换行符;如果想匹配换行符,需要加上参数re.DOTALL;例如:re.findall('a.b','abb a\nb abb',re.DOTALL)
  re.S是re.DOTALL的简写,也可以用这个;参考链接:https://www.pynote.net/archives/1202
  
* 不可单独使用;表示左侧字符串匹配0次或无穷次;性格贪婪
    print(re.findall(r'ab*', 'a ab abb abbbbb bbbbb'))
    >> ['a', 'ab', 'abb', 'abbbbb']
    
    解析:ab*
    首先*号的意思:0次或无穷次的意思指的是;*号左侧的【第一个字符】可以是0个,但是如果有,我就将所有连续的b字符都匹配到
    
+ 不可单独使用;表示左侧字符匹配一次或无穷次;性格贪婪
    print(re.findall(r'ab+', 'a ab abb abbbbb bbbbb'))
    >> ['ab', 'abb', 'abbbbb'] ps:这里的a就匹配不到了
    
    解析:和*的区别就在于,左侧至少要有一个,最多不限
    
? 不可单独使用;表示左侧字符匹配0次或1次 
    print(re.findall(r'ab?', 'a ab abb abbbbb bbbbb'))
    >> ['a', 'ab', 'ab', 'ab']
    
-------------------------------------------------------------------------
上面的到目前为止都不能自己去指定左侧字符出现的次数,下面就是讲解自定义
{m}: 左侧匹配m次,和{m,n}相比,是一个精确的
{m,n}: 左侧重复m次或n次;
        可以替换上面的
                   {0,1}==>?
                   {1,}==>+
                   {0,}==>*
        print(re.findall(r'ab{2,5}', 'a ab abb abbbbb bbbbb'))
        >> ['abb', 'abbbbb']

综合运用:找出字符中的所有整数和小数
    print(re.findall(r'\d+\.?\d*', '"asdfasdf123as1.13dfa12adsf1asdf3")'))
    >> ['123', '1.13', '12', '1', '3']
    分析:1. 首先必须是数字,使用\d匹配,数字至少要有一个或无穷个,用+
         2. 小数点,这里需要转移,不然会当成匹配符;整数没有小数点,但是小数有;因此小数点可以没有,但是有就只能有一个,用?
         3. 小数点后面,必须是数字且数字在整数的情况下数量为0,在小数的情况下可以有无限个,用*
         
-------------------------------------------------------------------------
上面说到的.可以匹配任意的字符,但是我们如果指向匹配指定的数字就无从下手,下面就是讲解自定义
[] : 匹配[]中的任意一个指定字符;[]内部的都会当成普通字符,但是也存在着一些特殊字符,下面展开介绍
    print(re.findall('a[501234]b', 'a1b a*b a-b'))
    >> ['a1b']
    
   []中为了方便,也存在着特殊字符以供调用
   特殊字符:- 连续的意思
            匹配0-9的数字可以写成[0-9],不可写成[9-0]
            匹配小写字母可以写成[a-z],不可写成[z-a]
            匹配大写字母可以写成[A-Z],不可写成[Z-A]
            上面的可以结合起来用[0-9a-zA-Z],一组的顺序可以随意写,例[a-za-9A-Z]
            注意:
                如果匹配的字符中-要当成普通字符去匹配,应该放到[]的开头或结尾,否则会被当成特殊字符
                上面的a-z这种范围型的不一定只能写a-z,a-cdefg...都行,只是普遍用a-z匹配全部小写
            
            print(re.findall('a[1*-]b', 'a1b a*b a-b'))
            >> ['a1b', 'a*b', 'a-b']

   特殊字符:^ 取反的意思
            print(re.findall('a[^1]b', 'a1b a*b a-b')) 
            >> ['a*b', 'a-b']
            
            print(re.findall('a[^0-9]b', 'a1b a*b a-b')) 
            >> ['a*b', 'a-b']
            
            注意:在[]外面,^代表的是匹配开头的单个字符

| : 匹配多个表达式中的任意一个;a|b表示满足条件中的任何一个即可匹配到
(): 分组;如果想将一个字符串分组取出,则使用()匹配;
    print(re.findall('(\d+)-(\d+)', '333-444'))
    >> [('333', '444')]
    分成了两组:这时候不同方法取组的方法不同,findall会将多个组放到一个元祖中;ps:外面的列表是findall默认的结果容器
    match,search等方法暂时不用
    
\b: 字符边界匹配

\:为什么要用r
print(re.findall('a\\c','a\c')) #对于正则来说a\\c确实可以匹配到a\c,但是在python解释器读取a\\c时,会发生转义,然后交给re去执行,所以抛出异常
print(re.findall(r'a\\c','a\c')) #r代表告诉解释器使用rawstring,即原生字符串,把我们正则内的所有符号都当普通字符处理,不要转义
print(re.findall('a\\\\c','a\c')) #同上面的意思一样,和上面的结果一样都是['a\\c']


re 模块的一般使用步骤如下:
使用 compile 函数将正则表达式的字符串形式编译为一个 Pattern 对象
通过 Pattern 对象提供的一系列方法对文本进行匹配查找,获得匹配结果(一个 Match 对象)
这样的好处是,如果多个地方用到了同一个正则表达式,一旦正则需要发生改变,只需要更改一处即可;


posted @ 2021-07-03 21:44  中州韵  阅读(105)  评论(0编辑  收藏  举报