Fork me on GitHub

正则表达式

一、正则基本符号

  • 1.什么是正则表达式
    正则表达式就是字符匹配的工具;是由正则符号和普通字符组成,来匹配不同规律的字符串

  • 2.Python对正则表达式的支持
    python中提供了一个re模块,用来支持正则表达式

  • fullmatch(正则表达式, 字符串) - 用正则表达式去完全匹配字符串,如果匹配成功返回匹配结果,失败返回None
    python中的正则表达式的写法:将正则内容写在字符串中,一般这个字符串的最前面会r/R

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    import re

    # 1 普通字符
    """
    普通字符在正则表达式中,代表字符本身
    """
    # 匹配一个字符串,第一个字符是'a',第二个字符是'b',第三个字符也是最后一个字符是'c'
    re_str = r'abc'
    result = re.fullmatch(re_str, 'abc')
    print(result)

    # 2 .(匹配任意字符)
    """
    在正则表达式中,.出现的位置,可以匹配一个任意字符
    注意:一个.只能匹配一个字符
    """
    # 匹配一个长度上3的字符串,并且第一个字符是'a',最后一个字符是'c',中间是任意字符
    re_str = r'a.c'
    result = re.fullmatch(re_str, 'a#c')
    print(result)

    # 3 \w(匹配字母数字或者下划线)
    """
    在正则表达式中,\w出现的位置,可以匹配一个任意的字母、数字或者下划线(其实也可以匹配Unicode编码中除了ASCII码剩下的部分)

    注意:
    一个\w只能匹配一个字符
    中文也能匹配
    """
    # 匹配一个长度是5的字符串,并且字符串的前两位是数字、字母和下划线,后面是三个任意字符
    re_str = r'\w\w...'
    result = re.fullmatch(re_str, '_好kll')
    print(result)

    # 4 \s(匹配空白字符)
    """
    空白字符包括:空格、制表符和换行符(空格,\t,\r,\n)
    """
    # 匹配一个长度是4的字符串,并且字符串前两位是字母数字或者下划线(中文),中间一个空白,再一个字母数字或者下划线(中文)
    re_str = r'\w\w\s\w'
    result = re.fullmatch(re_str, 'hj\t8')
    print(result)

    # 5 \d(匹配数字字符)
    # 匹配一个长度是5的字符串,字符串的前三位是数字字符,后两位是任意字符
    re_str = '\d\d\d..'
    result = re.fullmatch(re_str, '082de')
    print(result)


    # 6 \b(检测单词边界)
    """
    注意:检测\b出现的位置是否是单词边界,不会对字符进行匹配。
    当正则表达式中出现了\b,匹配的时候去掉\b,匹配成功后再看\b出现的位置是否是单词边界

    单词边界:字符串开头、字符串结尾、标点符号、空白符号等(只要能够将单词区分开的符号都属于单词边界)
    """
    # 匹配字符串'hello,world', 并且要求w前面是单词边界, h前面也是单词边界
    re_str = r'\bhello,\bworld'
    result = re.fullmatch(re_str, 'hello,world')
    print(result)

    >>>>
    <re.Match object; span=(0, 3), match='abc'>
    <re.Match object; span=(0, 3), match='a#c'>
    <re.Match object; span=(0, 5), match='_好kll'>
    <re.Match object; span=(0, 4), match='hj\t8'>
    <re.Match object; span=(0, 5), match='082de'>
    <re.Match object; span=(0, 11), match='hello,world'>
  • 7 ^(检测字符串开头)
    在match和fullmatch中没有意义, search、findall等中有意义

  • 8 $(检测字符串结尾

    1
    2
    3
    4
    # 匹配一个字符串,只有三位,分别是'The',并且e后面是字符串结尾
    re_str = r'The'
    result = re.fullmatch(re_str, 'The')
    print(result)
  • 9 \大写字母

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    """
    '\大写字母'对应的功能是'\小写字母'功能取反

    \W - 匹配非数字字母下划线
    \D - 匹配非数字字符
    \S - 匹配非空白字符
    \B - 检测非单词边界
    """
    # 匹配一个字符串,第一个字符是数字、第二个是非数字,第三个是空白,第四个是数字字母下划线,最后一个是a;
    # 并且要求a前面不是单词边界
    re_str = r'\d\D\s\w\Ba'
    result = re.fullmatch(re_str, '9H\t_a')
    print(result)
  • 10 字符集

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    """
    1.[普通字符集] - 匹配中括号出现的任意一个字符
    例如:[abc] - 匹配一个字符是a或者b或者c

    注意:a.一个中括号只能匹配一个字符
    b.正则中有特殊功能的单个符号在[]都表示符号本身 例如:. $ ^ + * ? |等
    c.匹配字符的组合符号,在中括号中保持原来的功能, 例如: \w \d \s \W \D \S
    """
    # 匹配一个长度是2的字符串,第一个字符是数字,第二个字符是b或者c或者=或者数字
    re_str = r'\d[bc=\d]'
    result = re.fullmatch(re_str, '24')
    print(result)

    """
    2.[字符1-字符2] - 表示字符1到字符2(注意:要求字符1的编码值要小于字符2)
    [a-z] - 表示匹配所有小写字母
    [A-Z] - 表示匹配所有大写字母
    [a-zA-Z] - 匹配所有的字母
    [1-7] - 匹配数字字符1到7
    [\u4e00-\u9fa5] - 匹配所有的中文

    [字符1字符2-] - 这儿的-表示减号本身
    """
    # 匹配一个长度是3的字符串,第一个字符是数字字符1到7中的一个,
    # 第二个字符是'a','b','c','-'中的一个,第三个字符是小写字母
    re_str = r'[1-7][abc-][a-z]'
    result = re.fullmatch(re_str, '6-z')
    print(result)
    >>>>
    <re.Match object; span=(0, 3), match='6-z'>
  • 11 [^字符集] - 匹配不在字符集中的任意一个字符

    [^abc] - 匹配除了’a’,’b’,’c’以外的其他任意一个字符
    [^\d] - 匹配除了数字字符以外的其他任意一个字符
    [^a-z] - 匹配除了小写字母以外的其他任意一个字符

[abc^] - 匹配’a’,’b’,’c’或者’^’中的任意一个字符

1
2
3
4
5
re_str = r'[^a-z]'
result = re.fullmatch(re_str, '是')
print(result)
>>>>
<re.Match object; span=(0, 1), match='是'>

二、正则控制匹配次数

  • 1 *(匹配0次或者多次)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    a* - a出现0次或者多次, '','a','aa', 'aaa'...都可以匹配
    \d* - 任意数字出现0次或者多次, '','1','12', '3772'...都可以匹配
    [abc]* - a,b或者c出现0次或者多次
    [A-F]* - A到F中任意字符出现0次或者多次

    注意:在[]外面的*的前面需要一个字符或者一个匹配字符的符号
    print(re.fullmatch(r'a*b', 'aaaaaaaaaab'))
    print(re.fullmatch(r'[abc]*', 'aabc'))
    print(re.fullmatch(r"[afadsaf]*",""))
    >>>>
    <re.Match object; span=(0, 11), match='aaaaaaaaaab'>
    <re.Match object; span=(0, 4), match='aabc'>
    <re.Match object; span=(0, 0), match=''>
  • 2

  • +(匹配1次或者多次)

    1
    2
    3
    4
    5
    6
    7
    """
    a+ - a至少出现一次
    \d+ - 数字至少出现一次
    """
    print(re.fullmatch(r'a+b', 'ab'))
    >>>>
    <re.Match object; span=(0, 2), match='ab'>
  • ?(匹配0次或者1次)

    1
    2
    3
    4
    5
    6
    7
    8
    """
    a? - a出现0次或者1次, '', 'a'可以匹配
    """
    # 写一个正则表达式匹配一个整数(正整数和负整数都可以),例如:123, 10, +100, -1234,
    re_str = r'[-+]?[1-9]\d*'
    print(re.fullmatch(re_str, '-12'))
    >>>>
    <re.Match object; span=(0, 3), match='-12'>
  • {}

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    """
    {N} - 匹配N次, 例如: a{3},匹配三个'a'
    {M,N} - 匹配M到N次, 例如: a{3, 5},匹配三个'a' 或者4个'a'或者5个'a'
    {,N} - 最多匹配N次(0~N) 例如:a{,3},'','a', 'aa', 'aaa'
    {M,} - 至少匹配M次 例如:a{3,} , 'aaa', 'aaaa', 'aaaaa'...
    """
    print(re.fullmatch(r'a{3,}', 'aaa'))

    # 练习:输入密码,要求检查密码输入是否合格(密码由字母和数字组成,数字不开头,6-12位)。给出提示
    password = input('密码:')
    re_str = r'[a-zA-Z][\da-zA-Z]{5,11}'
    result = re.fullmatch(re_str, password)
    if result:
    print('输入成功!')
    else:
    print('输入有误!')
    >>>>
    <re.Match object; span=(0, 3), match='aaa'>
    密码:4f5s4afd46as
    输入有误!

三、分之、捕获和贪婪

1.分之
  • 条件1 | 条件2 - 匹配条件1或者条件2
    \d{2}|[a-z] - 匹配两个数字字符或者一个小写字母
    a\d{2}|\w{2} - 匹配一个a后面两个数字,或者两个数字字母下划线

注意:正则中的分之也会出现短路,当条件1可以匹配,就不会再使用条件2进行匹配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
print(re.fullmatch(r'\d{2}|[a-z]', 'z'))
print(re.fullmatch(r'a\d{2}|\w{2}', 'sh'))

# 练习:写一个正则表达式,匹配所有的数字,包括正的、负的,整数,小数,0
# 例如:100, +100, -100, 12.5, -12.5, 0, 0.23, 0.012
"""
12, 12.34 : [+-]?[1-9]\d*[.]?\d*
0.123 : [+-]?0[.]\d+
0 : 0
"""
re_str = r'[-+]?[1-9]\d*[.]?\d*|[+-]?0[.]\d+|0'
print(re.fullmatch(re_str, '-0.02'))
>>>>
<re.Match object; span=(0, 5), match='-0.02'>

2 () - 捕获和分组
  • a.分组 - 将括号中的内容作为一个整体

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # 匹配一个字符串,前三位是'abc',后三位是三个数字或者三个大写字母
    re_str1 = r'abc\d{3}|abc[A-Z]{3}'
    re_str2 = r'abc(\d{3}|[A-Z]{3})'
    print(re.fullmatch(re_str2, 'abc123'))

    # 匹配一个字符串,以'数字小写字母'的形式出现3次
    re_str = r'(\d[a-z]){3}'
    print(re.fullmatch(re_str, '2s3f4h'))
    >>>>
    <re.Match object; span=(0, 6), match='abc123'>
    <re.Match object; span=(0, 6), match='2s3f4h'>
  • b 捕获
    通过正则获取符合条件的子串的时候,可以在正则表达式中加括号,匹配后只获取括号里面匹配到的内容

re.findall(正则表达式,字符串) - 在字符串中去获取符合正则表达式条件的所有的子串,返回一个列表

1
2
str1 = 'ahsa783+sdh*92dfjhjj78jhsda67jk'
print(re.findall(r'a(\d+)', str1)) # ['783', '67']

  • c 重复匹配
    带多个分组的正则表达式中可以分组的后面通过添加’\数字’来重复前面第几个分组中匹配到的内容

说明:\数字 - 这儿的数字代表前面第几个分组; \1代表第一个分组 \2代表第二个分组

3.贪婪
  • 匹配次数后加?就是贪婪匹配:*?, +?, ??, {M,N}?, {M,}? 表示尽可能少的重复
    1
    2
    3
    4
    5
    6
    7
    8
    re_str = 'a.+?b'
    re_str2 = 'a.+b' # 不使用贪婪
    str1 = 'xxxahdjbnnkbsssammmbkkk'
    print(re.findall(re_str2,str1))
    print(re.findall(re_str, str1))
    >>>>
    ['ahdjbnnkbsssammmb']
    ['ahdjb', 'ammmb']

4.转义符号

  • 在正则表达式中可以在有特殊意义或者特殊功能的符号前加\来取消其特殊功能
    \w - 代表两个字符,分别是’\’和w
    + - 代表+字符
    * - 代表*字符
    \? - 代表?字符
    [], (), {}表示字符的时候,前面也要加\

  • 注意:在中括号中, \必须加\表示\本身,^在最前面加\表示^本身, 在两个字符之间加\表示-本身

    四、re模块

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    import re

    # 1.compile(了解)
    """
    compile(正则表达式) - 将正则表达式转换成正则表达式对象
    转换成对象后可以通过对象调用对象方法
    """
    re_str = '\d{3}'
    re_obj = re.compile(re_str)

    # 调用模块中的函数
    print(re.fullmatch(re_str, '234'))
    # 调用对象方法
    print(re_obj.fullmatch('234'))

    # 2.match和fullmatch
    """
    a. fullmatch(正则表达式, 字符串) - 完全匹配,从字符串开头匹配到字符串结束
    b. match(正则表达式, 字符串) - 不完全匹配,只匹配字符串开头

    匹配成功返回匹配对象,匹配失败返回None
    """
    re_str = r'\d([A-Z]{2})'
    result1 = re.fullmatch(re_str, '2HK')
    print(result1)

    result2 = re.match(re_str, '8KLsjdddd==')
    print(result2)

    # 匹配对象
    """
    1.span - 匹配到的内容的范围,(开始下标, 结束下标), 结束下标取不到
    匹配对象.span() - 获取整个正则表达式匹配到的范围
    匹配对象.span(n) - 获取正则表达式中第n个分组匹配到的范围(前提是有分组)
    """
    print(result2.span())
    print(result2.span(1))

    """
    2.start和end - 获取匹配结果的开始下标和结束下标
    匹配对象.start()/匹配对象.end() - 获取整个正则表达式匹配到的开始下标/结束下标
    匹配对象.start(n)/匹配对象.end(n) - 获取正则表达式中第n个分组匹配到的开始/结束下标
    """
    print(result2.start(), result2.end())
    print(result2.start(1), result2.end(1))

    """
    3.group - 获取匹配到的内容
    匹配对象.group() - 获取整个正则表达式匹配到的内容
    匹配对象.group(n) - 获取正则表达式中第n个分组匹配到的内容
    """
    print(result2.group())
    print(result2.group(1))

    """
    4. string - 获取用来匹配的原字符串
    匹配对象.string
    """
    print(result2.string)

    # 3.search
    """
    search(正则表达式, 字符串) - 匹配字符串中第一个满足正则表达式的子串,如果匹配成功返回匹配对象否则返回None
    """
    str1 = 'abc123hks362shjjk990kll'
    result = re.search(r'\d{3}[a-z]{2}', str1)
    print(result)

    # 4.split
    """
    split(正则表达式, 字符串) - 在字符串中按照满足正则表达式条件的子串对字符串进行切割, 返回一个列表
    """
    str1 = 'ab+c7hdjd8jss-sk9sjj78s9kk*k'
    result = re.split(r'\d+|[+*-]+', str1)
    print(result)

    # 5.sub
    """
    sub(正则表达式, 新子串, 字符串) - 用新子串替换字符串中满足正则表达式的子串,返回一个替换后的字符串
    """
    str1 = '你丫是傻 叉吗? 我操你大爷的. F u c k you.'
    result = re.sub(r'[丫操艹]|F\s*u\s*c\s*k|傻\s*叉', '*', str1)
    print(result)

    # 6.findall
    """
    findall(正则表达式, 字符串) - 在字符串中获取满足正则表达式的所有的字符,返回一个列表,列表元素是字符串

    注意:如果这个正则表达式中有一个分组,结果是列表中只那个分组匹配到的结果
    如果这个正则表达式中分组的个数大于1,结果是一个列表,列表中的元素是元祖,元祖中是每个分组匹配到的内容
    """
    str1 = 'haja37jjkd89sdhs909nnna238==='
    result = re.findall(r'[a-zA-Z]{2,}(\d+)([a-z]+?)', str1)
    print(result)

    # 7.finditer
    """
    finditer(正则表达式, 字符串) - 获取字符串中满足正则表达式的内容,返回的是一个迭代器,迭代器中的元素是匹配对象
    """
    result = re.finditer(r'[a-zA-Z]{2,}(\d+)([a-z]+?)', str1)
    print(result)
    print(next(result))
    print(next(result))


    # 思考:写一个自己finditer
    def yt_finditer(pattern, string):
    re1 = re.search(pattern, string)
    while re1:
    yield re1
    string = string[re1.end():]
    re1 = re.search(pattern, string)


    print('============')
    result = yt_finditer(r'[a-zA-Z]{2,}(\d+)([a-z]+?)', str1)
    print(next(result))
    print(next(result))

    >>>>
    <re.Match object; span=(0, 3), match='234'>
    <re.Match object; span=(0, 3), match='234'>
    <re.Match object; span=(0, 3), match='2HK'>
    <re.Match object; span=(0, 3), match='8KL'>
    (0, 3)
    (1, 3)
    0 3
    1 3
    8KL
    KL
    8KLsjdddd==
    <re.Match object; span=(3, 8), match='123hk'>
    ['ab', 'c', 'hdjd', 'jss', 'sk', 'sjj', 's', 'kk', 'k']
    你*是*吗? 我*你大爷的. * you.
    [('37', 'j'), ('89', 's'), ('909', 'n')]
    <callable_iterator object at 0x0000022B3679DEF0>
    <re.Match object; span=(0, 7), match='haja37j'>
    <re.Match object; span=(7, 13), match='jkd89s'>
    ============
    <re.Match object; span=(0, 7), match='haja37j'>
    <re.Match object; span=(0, 6), match='jkd89s'>

下面为常用正则表达式

待续…

-------------本文结束 感谢您的阅读-------------
0%