1、知识点:


定义: 正则表达式是对字符串操作的一种逻辑公式,用事先定义好的一些特定字符、及这些字符的组合组成一个‘规则字符串’,实现对字符串的一种过滤
优点:灵活性、逻辑性和功能性非常强,可以用简单的方式快速实现字符串的控制
实现:re库 import re

match() 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,返回none,如果匹配,就返回匹配成功的结果,限制:起始位置匹配。
search() 在匹配时,会依次扫描字符串,直到找到第一个符合规则的字符串,然后返回匹配内容,如果搜索完还没有找到,就返回none,限制:找到第一个就会返回

表示范围:
[xyz] 字符集合,匹配所包含的任意一个字符
[a-z] 字符范围,匹配所包含范围内的任意字符

次数的限制:
*:匹配前面的子表达式任意次(大于等于0次)
+:匹配前面的子表达式一次或多次(大于等于1次)
?:匹配前面子表达式0次或1次
^:匹配字符串行首
$:匹配字符串行尾
{n}是一个非负整数,匹配确定的n次
{n,}n是一个非负整数,至少匹配n次
{n,m}至少匹配n次,最多匹配m次

\d 匹配一个数字字符,等价于[0-9]
\D 匹配一个非数字字符,等价于[^0-9]
\s 匹配任何不可见字符,包括空格 制表符 换页符等等,等价于[\f\n\r\t\v]
\S 匹配任何可见字符,等价于[^\f\n\r\t\v]
\w 匹配包括下划线的任何单词字符,等价于[A-Za-z0-9_]
\W 匹配任何非单词字符,等价于[^A-Za-z0-9_]
\b 匹配一个单词的边界,指单词和空格间的位置
\B 匹配非单词边界
. 匹配除\n和\r之外的任何单个字符
\f 匹配一个换页符
\n 匹配一个换行符
\r 匹配一个回车符
\t 匹配一个制表符
\v 匹配一个垂直制表符

|:将两个匹配条件进行逻辑或运算
():将()之间的表达式定义为组(group),并且将匹配这个表达式保存到一个临时的区域,返回组的内容

贪婪与非贪婪
贪婪模式:默认匹配模式,尝试匹配尽可能多的字符
非贪婪模式,匹配尽可能少的字符
在次数限制操作符,后面加上? 转换为非贪婪模式

正则修饰符
re.I 使匹配对大小写不敏感
re.M 多行匹配,影响^和$
re.S 使.匹配包括换行在内的所有字符
...

sub:除了使用正则表达式提取信息外,有时候还需要借助它来修饰文本,类似于replace替换
compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象


2、练习:
message = '钟南山、李春兰、乔杰'
    result = re.match('钟南山', message)
    print(result) # <re.Match object; span=(0, 3), match='钟南山'> span返回的是位置,0-3不包含3
    print(result.span()) # (0, 3) 返回位置
    print(result.group()) # 钟南山 返回匹配内容

    result = re.match('李春兰', message)
    print(result) # None 起始位置匹配不到返回none

    result = re.search('李春兰', message)
    print(result) # <re.Match object; span=(4, 7), match='李春兰'>

    message = '11ndinwd1oin111wq11doqje9dged'
    result = re.search('[abcde]', message) # 字符集合,匹配所包含的任意一个字符
    print(result) # <re.Match object; span=(3, 4), match='d'>

    result = re.search('[a-e]', message)
    print(result) # <re.Match object; span=(3, 4), match='d'>

    result = re.search('[a-e][0-9]', message) # 找到满足的第一个就会返回,不会继续匹配
    print(result) # <re.Match object; span=(7, 9), match='d1'>

    result = re.findall('[a-e][0-9]', message) # 搜索整个字符串,然后返回匹配正则表达式的所有内容,以列表的形式返回
    print(result) # ['d1', 'e9']

    print(dir(re))

    result = re.findall('[a-z][0-9]+[a-z]', message) # 配合次数+ 至少一次
    print(result) # ['d1o', 'n111w', 'q11d', 'e9d']

    result = re.findall('[a-z][0-9]*[a-z]', message) # 配合次数 * 任意次可以为0次
    print(result) # ['nd', 'in', 'wd', 'oi', 'n111w', 'q11d', 'oq', 'je', 'dg', 'ed']

    result = re.findall('[a-z][0-9]?[a-z]', message) # 配合次数 ? 最多一次
    print(result) # ['nd', 'in', 'wd', 'oi', 'wq', 'do', 'qj', 'e9d', 'ge']

    # 验证手机号码的正确性 1开头,11位数字
    phone_num = input("请输入手机号码:")
    '''
    请输入手机号码:123345656656666666666
    '''
    result = re.match('1[0-9]{10}', phone_num)
    print(result) # <re.Match object; span=(0, 11), match='12334565665'>

    result = re.findall('1[0-9]{10}', phone_num)
    print(result) # ['12334565665']

    result = re.findall('^1[0-9]{10}$', phone_num) # ^$限制行首行尾,只能为11位
    print(result) # ['12345678912']

    # 验证用户名的有效性
    phone_num = input("请输入用户名:")
    '''
    请输入手机号码:123345656656666666666
    '''
    result = re.match('1[0-9]{10}', phone_num)
    print(result)  # <re.Match object; span=(0, 11), match='12334565665'>

    result = re.findall('1[0-9]{10}', phone_num)
    print(result)  # ['12334565665']

    result = re.findall('^1[0-9]{10}$', phone_num)  # ^$限制行首行尾,只能为11位
    print(result)  # ['12345678912']

    # 验证QQ号码 从5到11,开头不能为0
    QQ_number = input("请输入您的QQ号:")
    result = re.findall('^[1-9][0-9]{4,10}$', QQ_number)
    print(result)

    # 验证用户名,字母(大小写)数字下划线组成,数字不能开头,长度大于8位
    user_name = input('请输入您的用户名:') #a1234567  1234567
    result = re.findall('^[A-Za-z_][A-Za-z0-9_]{7,}$', user_name)
    print(result) #['a1234567']
    result = re.findall('^\D\w{7,}$', user_name)
    print(result) #['a1234567'] [' 1234567']
    result = re.findall('^[A-Za-z_]\w{7,}$', user_name)
    print(result) #['a1234567'] []

    message = 'verb very never every'
    result = re.findall(r'\w+er\b', message) # \b为转义字符 \b匹配一个单词的边界,指单词和空格间的位置
    print(result) # ['never']

    result = re.findall('.e', message)  # . 匹配除\n和\r之外的任何单个字符
    print(result) # ['ve', 've', 'ne', 've', ' e', 've']

    result = re.findall('ev|ry', message)  # |:将两个匹配条件进行逻辑或运算
    print(result) # ['ry', 'ev', 'ev', 'ry']

    message = '''<div class="c-span4 opr-recommends-merge-item ">
            data-click="{'rsv_re_ename':'百度知道','rsv_re_uri':'44dde322323233'}"
            <div class="opr-recommends-merge-p">'''
    result = re.findall('div class=".+"', message) # 匹配class的内容,div class="
    print(result) # ['div class="c-span4 opr-recommends-merge-item "', 'div class="opr-recommends-merge-p"']

    result = re.findall("'rsv_re_ename':.+'", message) # 匹配class的内容,div class="
    print(result) # ["'rsv_re_ename':'百度知道','rsv_re_uri':'44dde322323233'"]

    result = re.findall("'rsv_re_ename':.+,", message) # 匹配class的内容,div class="
    print(result) # ["'rsv_re_ename':'百度知道',"]

    # 匹配 rsv_re_ename 和  rsv_re_uri
    result = re.findall("'rsv_re_ename':'(.+)','rsv_re_uri':'(.+)'", message) # 匹配class的内容,只返回组的内容
    print(result) # [('百度知道', '44dde322323233')]

    message = '<dt>首页</dt>'
    result = re.findall(r'^<\w+>(.+)</\w+>$', message)
    print(result)# ['首页']

    result = re.findall(r'^<(\w+)>(.+)</\1>$', message)  # 引用匹配,和前面匹配的内容一模一样,引用匹配从1开始
    print(result)# [('dt', '首页')]
    print(result[0][1]) # 首页

    message = '<dt><a>首页</a></dt>'
    result = re.findall(r'^<(\w+)><(\w)>(.+)</\2></\1>$', message)
    print(result) # [('dt', 'a', '首页')]
    print(result[0][2]) # 首页

    # 当匹配内容非常多时,可以给子表达式起名字,?P<name>
    result = re.findall(r'^<(?P<name1>\w+)><(?P<name2>\w)>(.+)</(?P=name2)></(?P=name1)>', message)
    print(result[0][2]) # 首页

    message = 'ccc739134792hd'
    result = re.findall('ccc\d+', message) # 默认贪婪模式
    result1 = re.findall('ccc\d+?', message) # 次数后面加? 转换为非贪婪模式
    print(result, result1) #['ccc739134792'] ['ccc7']

    message = '''<dt><a>首页
                内容在这里</a></dt>'''
    result = re.findall(r'^<(\w+)><(\w)>(.+)</\2></\1>$', message)
    print(result) # []

    result = re.findall(r'^<(\w+)><(\w+)>(.+)</\2></\1>$', message, re.S) # re.S 使.匹配包括换行在内的所有字符
    print(result) # [('dt', 'a', '首页\n                内容在这里')]

    content = 'dh932hf9f9623hhh2556'
    content = re.sub('\d', 'O', content) # 将数字转换为O
    print(content) # dhOOOhfOfOOOOhhhOOOO

    # 分别将3个日期中的时间去掉
    content1 = '2020-12-15 12:00'
    content2 = '2020-12-17 12:00'
    content3 = '2020-12-22 12:00'
    pattern = re.compile('\d{2}:\d{2}')  # compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,多个地方引用,实现复用
    result1 = re.sub(pattern, '', content1)
    result2 = re.sub(pattern, '', content2)
    result3 = re.sub(pattern, '', content3)
    print(result1, result2, result3) # 2020-12-15  2020-12-17  2020-12-22