5.5正则表达式学习笔记及作业

5.5正则表达式学习笔记及作业

认识正则表达式

正则表达式: 解决字符串问题的工具(让复杂的字符串问题变得简单的一个工具)
问题:验证输入的手机号是否合法。
abc - 不是
123 - 不是
12345678901 - 不合法
13354627381 - 合法
1335462738189 - 不合法
方法1
def is_tel_num(tel_no: str):
    if len(tel_no) != 11:
        return False

    if tel_no[0] != '1':
        return False

    if tel_no[1] not in '3456789':
        return False

    return tel_no.isdigit()


tel = '13354627381'
print(is_tel_num(tel))
from re import fullmatch,findall


# 方法2:
def is_tel_num2(tel_no: str):
    return fullmatch(r'1[3-9]\d{9}', tel_no) != None


tel = '13354622381'
print(is_tel_num2(tel))
message = '收到回复就234数据jssh 78师傅好看2391金虎送福23刷卡机sshs34'
# 234、78、2391、23、34

# 方法1:
all_num = []
num_str = ''
for index in range(len(message)):
    if message[index].isdigit():
        num_str += message[index]
    else:
        all_num.append(num_str)
        num_str = ''
all_num.append(num_str)
all_num = [int(x) for x in all_num if x]

print(all_num)
# 方法2:
message = '收到回复就234数据jssh 78师傅好看2391金虎送福23刷卡机sshs34'
all_num2 = findall(r'\d+', message)
print(all_num2)

匹配类符号

from re import fullmatch

1. re模块

"""
re模块是python用来支持正则表达式的一个模块
re模块中提供了各种和正则相关的函数:fullmatch、search、findall、match、split、sub等等

fullmatch(正则表达式, 字符串)  -  判断整个字符串是否完全符号正则表达式描述的规则。如果不符合返回值是None

python中提供正则表达式的方式:r'正则表达式'
js中提供正则表达式的方式:/正则表达式/
"""

2. 匹配类符号 - 一个正则符号表示一类字符

匹配类符号在正则中的作用:用来要求字符串中某个位置必须是什么样的字符
1)普通符号 - 在正则表达式中表示这个符号本身,对应字符串中的字符的要求就是符号本身。
要求字符串:总共有3个字符,第一个是’a’,第二个是’b’,第三个是’c’
result = fullmatch(r'abc', 'abc')
print(result)

result = fullmatch(r'abc', 'mnd')
print(result)
2) . - 匹配一个任意字符
要求字符串:总共有3个字符,第一个是’a’,最后一个是’c’,中间可以是任何符号
result = fullmatch(r'a.c', 'a*c')
print(result)

result = fullmatch(r'..xy', '是sxy')
print(result)
3)\d - 匹配一个任意数字
result = fullmatch(r'a\dc', 'a2c')
print(result)

result = fullmatch(r'\d\d\d..', '823m是')
print(result)
4)\s - 匹配任意一个空白字符
空白字符包括:空格、\n、\t
result = fullmatch(r'a\sb', 'a b')
print(result)
5)\w - 匹配任意一个数字、字母或者下划线或者中文
result = fullmatch(r'a\wb', 'a3b')
print(result)
6)\大写字母 - 与相应的小写字母的功能相反
"""
\D  -   匹配任意一个非数字字符
\S  -   匹配任意一个非空白字符
\W 
"""

result = fullmatch(r'a\Db', 'a2b')
print(result)       # None
result = fullmatch(r'a\Db', 'a)b')
print(result)
7) [字符集] - 匹配字符集中任意一个字符
注意:一个[]只能匹配一个字符
"""
[多个普通符号] -  例如:[abc12], 在'a'、'b'、'c'、'1'、'2'五个符号中任意一个可以匹配 
[包含\开头的特殊符号]  - 例如:[mn\d]、[m\dn]、[\dmn], 要求是m或者n或者任意一个数字 
[字符1-字符2]   -   例如:[a-z],要求是任意一个小写字母
                        [a-zA-Z],要求是任意一个字母
                        [2-9a-z],要求是2到9或者是任意一个小写字母
                        [\u4e00-\u9fa5],要求是任意一个中文
                        [\u4e00-\u9fa5\dabc]
                   注意:[]中如果-不在两个字符之间,就不能表示谁到谁,那它就是个普通符号
"""
result = fullmatch(r'1[xyzmn]2', '1n2')
print(result)


result = fullmatch(r'a[mn\d]b', 'a9b')
print(result)

result = fullmatch(r'1[a-z][a-z]2', '1hm2')
print(result)

result = fullmatch(r'a[x\u4e00-\u9fa5\dy]b', 'ayb')
print(result)

result = fullmatch(r'1[-az]2', '1-2')
print(result)
8) [^字符集] - 匹配不在字符集中的任意一个字符
result = fullmatch(r'1[^xyz]2', '1x2')
print(result)

result = fullmatch(r'1[^\dab]2', '1M2')
print(result)


result = fullmatch(r'a[^2-9]b', 'a3b')
print(result)

匹配次数

from re import fullmatch, search

1. * - 匹配0次或者多次(任意次数)

"""
a*  -   a出现任意次数
\d*  -  任意多个\d  -> 任意多个数字
[abc]*  -  任意多个[abc]  -> 任意多个(a或者b或者c)
...
"""
result = fullmatch(r'a*b', 'aaaaaaab')
print(result)

result = fullmatch(r'\d*b', '21222b')
print(result)

result = fullmatch(r'[A-Z]*b', 'KDBb')
print(result)

2. + - 匹配1次或者多次(至少1次)

result = fullmatch(r'a+b', 'aaaaab')
print(result)

3. ? - 0次或1次

result = fullmatch(r'-?123', '-123')
print(result)

result = fullmatch(r'[+-]?123', '+123')
print(result)

4. {} - 重复前面字符次数

"""
{N}   -  N次
{M,N} -  M到N次
{M,}  -  至少M次
{,N}  -  最多N次

* == {0,}
+ == {1,}
? == {0,1}
"""
result = fullmatch(r'\d{3}abc', '623abc')
print(result)

result = fullmatch(r'\d{2,5}abc', '2234abc')
print(result)

5. 贪婪和非贪婪

在匹配次数不确定的时候,匹配模式分为贪婪和非贪婪两种,默认是贪婪的。
"""
匹配次数不确定:*、+、?、{M,N}、{M,}、{,N}

贪婪和非贪婪:在次数不确定的情况下,对应的字符串在不同次数下有多种匹配结果,贪婪取最多次数对应的结果。(前提是匹配成功有多种情况)
            非贪婪取最少次数对应的结果。
            
贪婪:*、+、?、{M,N}、{M,}、{,N}
非贪婪:*?、+?、??、{M,N}?、{M,}?、{,N}?
"""
result = fullmatch(r'\d+?', '26373')
print(result)       # '26373'


# search(正则表达式, 字符串)   -  在字符串中查找第一个满足正则表达式的字串
# 2 -> 1 26 -> 2  263 -> 3   2637 -> 4  26373 -> 5
result = search(r'\d+?', '水电费国家26373sfdhgahj')
print(result)


# 'amnb' -> 2   'amnbxnxb'  -> 6   'amnbxnxb盛世b'  -> 9
result = search(r'a.*b', r'施工方回家啊amnbxnxb盛世b-2---==')
print(result)   # 'amnbxnxb盛世b


result = search(r'a.*?b', r'施工方回家啊amnbxnxb盛世b-2---==')
print(result)   # 'amnb'


# '<p>你是好吗</p>'  - 4     '<p>你是好吗</p><a>百度</a><p>hello world!</p>'
html = '<body><span>开始!</span><p>你是好吗</p><a>百度</a><p>hello world!</p></body>'
result = search(r'<p>(.*?)</p>', html)
print(result, result.group(1))


result = search(r'a.+?c', '手机端发挥amnc你好c会计核算地方abc')
print(result)

分组和分支

from re import fullmatch, findall

1. 分组 - ()

分组就是在正则中用括号将正则中的部分内容括起来就形成了一个分组
1)整体操作
2) 重复
在正则中:\N可以重复\N所在的位置的前面的第N个分组匹配到的内容
3) 捕获 - 获取正则匹配结果中的部分内容
匹配:两个字母两个数字的结构重复3次,‘mn78jh56lm89’
result = fullmatch(r'[a-zA-Z]{2}\d\d[a-zA-Z]{2}\d\d[a-zA-Z]{2}\d\d', 'mn78jh56lm89')
print(result)

result = fullmatch(r'([a-zA-Z]{2}\d\d){3}', 'mn78jh56lm89')
print(result)
匹配:'23abc23、‘59abc59’ - 成功
‘23abc56’ - 失败
# result = fullmatch(r'\d\dabc\d\d', '23abc56')
# print(result)

result = fullmatch(r'(\d\d)abc\1', '23abc23')
print(result)


result = fullmatch(r'(\d{3})([a-z]{2})-\2\1=\1{3}', '876nm-nm876=876876876')
print(result)


result = fullmatch(r'(((\d{2})[A-Z]{3})([a-z]{2}))-\2-\1-\3', '34MNGbn-34MNG-34MNGbn-34')
print(result)


result = findall(r'[a-z]\d\d', '爱喝酒2空间数据78,明年and45没精神2341==hsn89=江=263')
print(result)   # ['d45', 'n89']

result = findall(r'[a-z](\d\d)', '爱喝酒2空间数据78,明年and45没精神2341==hsn89=江=263')
print(result)       # ['45', '89']

2. 分支 - |

正则1|正则2 - 先用正则1进行匹配如果匹配成功就直接成功,如果匹配失败再用正则2进行匹配,如果匹配成功就成功,如果失败就失败
匹配: abc后面是两个任意数字或者两个任意的大写字母, ‘abc34’、‘abcKJ’
result = fullmatch(r'abc\d\d|abc[A-Z]{2}', 'abc34')
print(result)

result = fullmatch(r'abc(\d\d|[A-Z]{2})', 'abcKL')
print(result)

检测类符号和转义符号

from re import fullmatch, findall, search

1. 检测类符号(了解)

检测类符号不是匹配符号,不会要求某个位置必须是什么样的字符,而是用检测某个位置是否符号相关要求
1)\b - 检测是否是单词边界
"""
单词边界  -  凡是可以用来将两个单词区分开的符号,例如:空白字符、标点符号、字符串开头、字符串结尾
"""
result = findall(r'\b\d+\b', '23数据2367skjj,89是2039,按键是否 768hsj,237 很久没79ssjs 89')
print(result)
2)\B - 检测是否是非单词边界
3)^ - 检测是否是字符串开头([]外面)
4)$ - 检测是否是字符串结尾
result = fullmatch(r'1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}', '13578237392')
print(result)

result = search(r'^1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}$', '13578237392')
print(result)

# 电话号码正则表达式 ^1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}$

2. 转义符号

正则中的转义符号是指在本身就具备特殊功能的符号前加\,让它本身具备的特殊功能消失变成一个普通符号。
写一个正则匹配一个小数: 2.3
result = fullmatch(r'\d\.\d', '2.3')
print(result)

# '23+78'
result = fullmatch(r'\d\d\+\d\d', '65+23')
print(result)

# '(护具)'
result = fullmatch(r'\([\u4e00-\u9fa5]{2}\)', '(护具)')
print(result)

# '\dabc'
result = fullmatch(r'\\dabc', '\dabc')
print(result)


# '-abc'、'Mabc'、'Nabc'
result = fullmatch(r'[mn\]]abc', ']abc')
print(result)
补充:独立存在有特殊意义的符号,放到[]中特殊功能会直接消失变成一个普通符号,例如:+、*、.、?、)、(等
result = fullmatch(r'[.+*?$]ab[.]c', '+ab.c')
print(result)

re模块

import re

1. 常用的函数

"""
1)re.fullmatch(正则, 字符串)   -  用整个字符串和正则表达式进行匹配,如果匹配成功返回匹配对象,匹配失败返回None
2)re.match(正则, 字符串)      -   匹配字符串开头,如果匹配成功返回匹配对象,匹配失败返回None
3)re.search(正则, 字符串)   -  匹配字符串中第一个满足正则的字串,如果匹配成功返回匹配对象,匹配失败返回None
4)re.findall(正则, 字符串)   -   获取字符串中所有满足正则的子串,返回值是列表,列表中的元素是匹配到的字符串
5)re.finditer(正则, 字符串)  -  获取字符串中所有满足正则的子串,返回一个迭代器,迭代器中的元素是匹配对象
6)re.split(正则, 字符串)     -   将字符串中所有满足正则的字串作为切割点对字符串进行切割,返回一个列表,列表中的元素是字符串
7)re.sub(正则, 字符串1, 字符串2)   - 将字符串2中所有满足正则的字串全部替换成字符串1
"""
1)re.fullmatch(正则, 字符串) - 用整个字符串和正则表达式进行匹配,如果匹配成功返回匹配对象,匹配失败返回None
result = re.fullmatch(r'\d{3}', '728')
print(result)
2)re.match(正则, 字符串) - 匹配字符串开头,如果匹配成功返回匹配对象,匹配失败返回None
result = re.match(r'\d{3}', '728会计师大会的咖啡机')
print(result)
3)re.search(正则, 字符串) - 匹配字符串中第一个满足正则的字串,如果匹配成功返回匹配对象,匹配失败返回None
result = re.search(r'\d{3}', '手机号728会计师大262会的咖啡机')
print(result)
4)re.findall(正则, 字符串) - 获取字符串中所有满足正则的子串,返回值是列表,列表中的元素是匹配到的字符串
result = re.findall(r'\d{3}', '手机号728会计师大262会的咖0923啡机')
print(result)       # ['728', '262', '092']

result = re.findall(r'[a-z]\d{3}', '手机号728会计师大m262会的咖0923啡k7823机')
print(result)   # ['m262', 'k782']

result = re.findall(r'[a-z](\d{3})', '手机号728会计师大m262会的咖0923啡k7823机')
print(result)   # ['262', '782']

result = re.findall(r'([a-z])(\d{3})', '手机号728会计师大m262会的咖0923啡k7823机')
print(result)   # [('m', '262'), ('k', '782')]
5)re.finditer(正则, 字符串) - 获取字符串中所有满足正则的子串,返回一个迭代器,迭代器中的元素是匹配对象
result = re.finditer(r'\d{3}', '手机号728会计师大262会的咖0923啡机')
print(list(result))


result = re.finditer(r'([a-z])(\d{3})', '手机号728会计师大m262会的咖0923啡k7823机')
print(list(result))
6)
re.split(正则, 字符串) - 将字符串中所有满足正则的字串作为切割点对字符串进行切割,返回一个列表,列表中的元素是字符串
re.split(正则, 字符串, N)
result = re.split(r'\d{3}', '手机号728会计师大m262会的咖0923啡k7823机')
print(result)       # ['手机号', '会计师大m', '会的咖', '3啡k', '3机']

message = '安徽师a水电费b煽风点火可见a烧开后b顺丰科技c水电费即可'
result = re.split(r'[abc]', message)
print(result)

result = re.split(r'[abc]', message, 3)
print(result)
7)re.sub(正则, 字符串1, 字符串2) - 将字符串2中所有满足正则的字串全部替换成字符串1
re.sub(正则, 字符串1, 字符串2, N)
message = '安徽师a水电费b煽风点火可见a烧开后b顺丰科技c水电费即可'
将a、b、c都替换成’++’
# new_message = message.replace('a', '++')
# new_message = new_message.replace('b', '++')
# new_message = new_message.replace('c', '++')
# print(new_message)

result = re.sub(r'[abc]', '++', message)
print(result)


result = re.sub(r'\d', '0', '手机号728会计师大m262会的咖0923啡k7823机')
print(result)

result = re.sub(r'\d', '0', '手机号728会计师大m262会的咖0923啡k7823机', 5)
print(result)

2. 匹配对象

result = re.search(r'([a-z]{2})-(\d{3})', '手机号ag-728会计师大262会的咖啡机')
print(result)       # <re.Match object; span=(3, 9), match='ag-728'>

# 1)获取匹配结果对应的字符串
# a.获取整个正则匹配到的字符串: 匹配对象.group()
r1 = result.group()
print(r1)       # 'ag-728'

# b.获取某个分组匹配到的结果: 匹配对象.group(N)
r2 = result.group(1)
print(r2)    # 'ag'

r3 = result.group(2)
print(r3)    # '728'

# 2)获取匹配结果在原字符串中的位置信息
r1 = result.span()
print(r1)

r2 = result.span(2)
print(r2)

3.参数

# 1)单行匹配和多行匹配
"""
多行匹配的时候.不能和'\n'进行匹配 (默认):flags=re.M、(?m)
单行匹配的时候.可以和'\n'进行匹配:flags=re.S、(?s)
"""
# 设置单行匹配
result = re.fullmatch(r'a.c', 'a\nc', flags=re.S)
print(result)

result = re.fullmatch(r'(?s)a.c', 'a\nc')
print(result)

# 2)忽略大小写
"""
默认情况下大写字母和小写字母是不能匹配,忽略大小写以后大写字母就可以和对应的小写字母匹配
方法:flags=re.I、(?i)
"""
result = re.fullmatch(r'abc', 'aBc', flags=re.I)
print(result)

result = re.fullmatch(r'(?i)12[a-z]', '12N')
print(result)

# 3)既忽略大小写又要单行匹配
# 方法:flags=re.I|re.S、(?si)
result = re.fullmatch(r'abc.12', 'aBc\n12', flags=re.I|re.S)
print(result)

result = re.fullmatch(r'(?si)abc.12', 'aBc\n12')
print(result)

作业

利用正则表达式完成下面的操作:

一、不定项选择题
  1. 能够完全匹配字符串"(010)-62661617"和字符串"01062661617"的正则表达式包括(A)

    A. r"\(?\d{3}\)?-?\d{8}"
    B. r"[0-9()-]+"
    C. r"[0-9(-)]*\d*"
    D.r"[(]?\d*[)-]*\d*"

  2. 能够完全匹配字符串"back"和"back-end"的正则表达式包括(A)
    A. r'\w{4}-\w{3}|\w{4}'
    B. r'\w{4}|\w{4}-\w{3}'
    C.r'\S+-\S+|\S+'
    D. r'\w*\b-\b\w*|\w*'

  3. 能够完全匹配字符串"go go"和"kitty kitty",但不能完全匹配“go kitty”的正则表达式包括(D)
    A.r '\b(\w+)\b\s+\1\b'
    B. r'\w{2,5}\s*\1'
    C. r'(\S+) \s+\1'
    D. r'(\S{2,5})\s{1,}\1'

  4. 能够在字符串中匹配"aab",而不能匹配"aaab"和"aaaab"的正则表达式包括(C)
    A. r"a*?b"
    B. r"a{,2}b"
    C. r"aa??b"
    D. r"aaa??b"

二、编程题

1.用户名匹配

​ 要求: 1.用户名只能包含数字 字母 下划线

​ 2.不能以数字开头

​ 3.⻓度在 6 到 16 位范围内

from re import fullmatch


def username(name):
    re_str = r"[a-zA-Z_][a-zA-Z_1-9]{5,15}"
    result = fullmatch(re_str, name)
    if result:
        return True
    else:
        return False
  1. 密码匹配

​ 要求: 1.不能包含!@#¥%^&*这些特殊符号

​ 2.必须以字母开头

​ 3.⻓度在 6 到 12 位范围内

from re import fullmatch


def is_keyword(keyword: str):
    return fullmatch(r'[a-zA-Z][^!@#¥%^&*]{5,11}', keyword)
  1. ipv4 格式的 ip 地址匹配
    提示: IP地址的范围是 0.0.0.0 - 255.255.255.255
from re import fullmatch, findall


def is_address(address: str):
    return fullmatch(r'(([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}(\d{1,2}|1\d{2}|2[0-4]\d|25[0-5])', address)
  1. 提取用户输入数据中的数值 (数值包括正负数 还包括整数和小数在内) 并求和
例如:“-3.14good87nice19bye” =====> -3.14 + 87 + 19 = 102.86
from re import fullmatch, findall
from functools import *


def sum_(str1):
    re_str = r"[+-]?\d+[.]?\d+"
    result = findall(re_str, str1)
    print(reduce(lambda x, item: x+float(item), result, 0))
  1. 验证输入内容只能是汉字

    from re import fullmatch
    
    
    def is_chinese(chinese: str):
        return fullmatch(r'[\u4e00 -\u9fa5]+', chinese)
    
  2. 匹配整数或者小数(包括正数和负数)

    from re import fullmatch
    
    
    def is_numbers(numbers: str):
        return fullmatch(r'[+-]?([1-9]\d*|0)(\.\d+)?', numbers)
    
  3. 验证输入用户名和QQ号是否有效并给出对应的提示信息

    要求:
    用户名必须由字母、数字或下划线构成且长度在6~20个字符之间
    QQ号是5~12的数字且首位不能为0

    from re import fullmatch
    
    username = r'(?i)[a-z1-9_]{6,20}'
    is_username = input('请输入用户名:')
    result_name = fullmatch(username, is_username)
    if result_name:
        print('用户名有效')
    else:
        print('用户名无效')
    keyword = r'[1-9]\d{4,11}'
    is_keyword = input('请输入密码:')
    result_qq = fullmatch(keyword, is_keyword)
    if result_qq:
        print('QQ号有效')
    else:
        print('QQ号无效')
    
  4. 拆分长字符串:将一首诗的中的每一句话分别取出来

    ​ poem = ‘窗前明月光,疑是地上霜。举头望明月,低头思故乡。’

    from re import split
    
    poem = '窗前明月光,疑是地上霜。举头望明月,低头思故乡。'
    result = split(r'[,。]', poem)
    for x in result:
        print(x)
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值