正则表达式及作业
-
正则表达式
-
什么是正则表达式
# 正则是一种用来处理文本数据的一种工具。(一般用于处理复杂的文本问题) # 1)检测输入的数据是否是手机号? # 2)检查输入的ip地址是否合法? # 3)获取字符串中所有的数字数据:'sjhfj23世纪东方和79sk试试928sjd' # ....
-
正则表达式的语法 - 用不同的符号来描述字符串规则
# 1) 匹配类符号 # 2) 检测类符号 # 3) 控制次数的符号 # 4) 分组和分支 # 5) 其他常用参数 # fullmatch(正则表达式, 字符串) - 检测字符串是否符合正则表达式描述的规则,如果不符合返回None # '正则表达式' - Python "正则表达式" - OC/python /正则表达式/ - js
-
-
正则匹配符号
-
普通字符 - 特殊符号以外的字符就是普通字符
# 普通字符在正则中表示这个符号本身 re_str = 'abc' # 需要一个长度是3的字符串,并且第一个字符是a, 第二个字符是b, 第三个字符是c print(fullmatch(re_str, 'abc'))
-
.
- 匹配一个任意字符re_str = 'a.c' # 需要一个长度是3的字符串, 并且第一个字符是a, 最后一个字符是c,中间是任意字符 print(fullmatch(re_str, 'a胡c')) re_str = '..ab' # 一个长度是4的字符串,ab前面是任意两个字符 print(fullmatch(re_str, 'o9ab'))
-
\d
- 匹配任意一个数字字符re_str = r'ab\d' # 一个长度是3的字符串,ab后面是一个任意数字 print(fullmatch(re_str, 'ab3'))
-
\w
- 匹配任意一个数字、字母或者下划线(基于ASCII码, 了解有解释与实际出入)re_str = r'\w123' print(fullmatch(re_str, '好123'))
-
\s
- 匹配任意一个空白字符# 空白字符 - 空格、\t、\n re_str = r'123\sabc' print(fullmatch(re_str, '123 abc'))
-
\D
(匹配任意非数字字符)、\S
(匹配任意一个非空白字符)# \D - 匹配任意一个非数字字符 # \S - 匹配任意一个非空白字符 print(fullmatch(r'abc\S123\D', 'abcM123='))
-
[字符集]
- 匹配字符集中的任意一个字符''' [ab12] - 匹配a、b、1或者2中任意一个字符 [ab\d]、[\dab]、[a\db]、[ab0123456789] - 匹配a、b、或者0到9中任意一个字符 [0-9] - 匹配0到9中任意一个字符 [56789]、[5-9] - 匹配5到9中任意一个字符 [a-z] - 匹配任意一个小写字母 [A-Z] - 匹配任意一个大写字母 [a-zA-Z] - 匹配任意一个字母 [a-zA-Z\d_] - 匹配任意一个字母、数字、下划线 [\u4e00-\u9fa5] - 匹配任意一个中文 注意:如果[]中-在两个字符之间表示范围,如果-不在两个字符之间,它不具备特殊功能表示这个符号本身, -在[]外面也是普通符号 ''' re_str = r'a[xyz]b' print(fullmatch(re_str, 'ayb')) print(fullmatch(r'abc[2-5]', 'abc4')) print(fullmatch(r'[\u4e00-\u9fa5]abc', '好abc')) # print(fullmatch(r'[z-a]abc', 'wabc')) # 报错 print(fullmatch(r'[ac-]123', '-123'))
-
[^字符集]
- 匹配除了字符集以外的任意一个字符print(fullmatch(r'[^axy]123', 'k123')) print(fullmatch(r'[^a-zA-Z]123', '-123')) # 注意:[]里面,^只有放在最前面才有特殊意义,在其他位置表示^本身 print(fullmatch(r'[a-z^]123', '^123')) # print(fullmatch('[abc][abc]abc'))
-
-
检测类符号
-
什么是检测类符号
''' 检测类符号在正则中不会影响字符串长度,它们的作用是在匹配成功以后检测检测类符号所在的位置是否符号要求 '''
-
\b
- 检测是否是单词边界# 单词边界 - 凡是能够将两个单词区分开的所有的符号,主要有:空白、标点符号、字符串开头和字符结尾 re_str = r'abc \b123' print(fullmatch(re_str, 'abc 123')) re_str = r'abc\b.123' print(fullmatch(re_str, 'abc,123')) str1 = '数据集,890,shs323节省时间34jsj 922 失敬失8敬283' result = findall(r'\b\d+\b', str1) print(result)
-
\B
- 检测是否不是单词边界result = findall(r'\B\d+\B', str1) print(result)
-
^
- 检测是否是字符串开头([]外面)re_str = r'^\dabc' print(findall(re_str, '7abc啥时间2abc数据9abc是6abc'))
-
$
- 检测是否是字符串结尾([]外面)re_str = r'\dabc$' print(findall(re_str, '7abc啥时间2abc数据9abc是6abc'))
-
-
匹配次数
-
*
匹配0次或多次""" a* - 匹配0个或者多个a .* - 匹配0个或者多个任意字符 \d* - 相当于任意多个\d [xyz]* - 相当于任意多个[xyz] """ re_str = r'a*123' print(fullmatch(re_str, 'aaaaaa123')) re_str = r'.*123' print(fullmatch(re_str, 'asc123')) re_str = r'\d*abc' print(fullmatch(re_str, '78908887abc')) re_str = r'[xyz]*123' print(fullmatch(re_str, 'xxyz123'))
-
+
1次或者多次 -
?
0次或者1次 -
{}
""" {N} - 匹配N次 {M,N} - 匹配M~N次 {,N} - 匹配0~N次(最多N次) {M,} - 匹配至少M次 """ print(fullmatch(r'\d{3}abc{5}', '722abccccc')) print(fullmatch(r'\d{3,5}abc', '72126abc')) print(fullmatch(r'\d{,2}abc', '23abc')) print(fullmatch(r'\d{2,}abc', '2231abc'))
-
贪婪和非贪婪
""" 贪婪和非贪婪模式是在匹配次数不确定的时候才会出现:*、+、?、{M,N}、{,N}、{M,} 贪婪和非贪婪:在能够匹配成功的情况下,如果对应的匹配次数有多种,贪婪模式选最多的那个次数,非贪婪选最少的那个次数。 贪婪:*、+、?、{M,N}、{,N}、{M,} 非贪婪:*?、+?、??、{M,N}?、{,N}?、{M,}? """ print(search(r'\d{3}', 'shsj234色即是空889====902')) # <re.Match object; span=(4, 7), match='234'> re_str = r'a.+b' print(search(re_str, '试试amnbxyzb是计算机数据')) # <re.Match object; span=(2, 10), match='amnbxyzb'> re_str = r'a.+?b' print(search(re_str, '试试amnbxyzb是计算机数据')) # <re.Match object; span=(2, 6), match='amnb'> re_str = r'a.+b' print(search(re_str, '试试amnbxyz是计算机数据')) # <re.Match object; span=(2, 6), match='amnb'>
-
-
分支和分组
-
分组 -
()
""" 应用一:将正则表达式中的一部分用()括起来表示一个整体,然后进行整体相关操作 应用二:通过\M来重复它前面第M个分组匹配到的内容 应用三:捕获(获取结果的时候只取某个分组对应的内容) """ # hj78hu23kk90 re_str = r'([a-zA-Z]{2}\d\d){3}' print(fullmatch(re_str, 'hj78hu23kk90')) # mn123mn、xy123xy re_str = r'([a-z]{2})123\1' print(fullmatch(re_str, 'mn123mn')) re_str = r'(\d{2})([A-Z]{3})\1\2' print(fullmatch(re_str, '12MNA12MNA')) # re_str = r'(\d{2})\2([A-Z]{3})\1' # print(fullmatch(re_str, '12MNHMNH12')) # 报错! re_str = r'(\d{2})([A-Z]{3})\1{2}\2' print(fullmatch(re_str, '12KAM1212KAM')) re_str = r'[a-z](\d{3})' result = findall(re_str, 'hsjs234失敬失敬你a8393sjjk9901啥时间---234看看嘛238') print(result)
-
分支 -
|
# 正则1|正则2 # |相当于或者 # abc123、abcMN re_str = r'abc\d{3}|abc[A-Z]{2}' print(fullmatch(re_str, 'abcMN')) re_str = r'abc\d{3}|[A-Z]{2}' print(fullmatch(re_str, 'MK')) re_str = r'abc(\d{3}|[A-Z]{2})' print(fullmatch(re_str, 'abc234'))
-
-
re模块(
import re
)-
compile(正则表达式) - 创建正则表达式对象
re_obj = compile(r'\d{3}') print(fullmatch(r'\d{3}', '234')) print(re_obj.fullmatch('384')) # 用compile 定义了正则表达式,直接调用方法 给操作的字符串
-
匹配相关方法
-
fullmatch(正则表达式, 字符串)
- 完全匹配,判断整个字符串是否符合正则表达式描述的规则。如果不符合返回None,如果符合返回匹配对象 -
match(正则表达式, 字符串)
- 匹配开头,判断字符串开头是否符合正则表达式描述的规则。如果不符合返回None,如果符合返回匹配对象re_str = r'[a-z]{3}' print(fullmatch(re_str, 'hsm')) # 完全匹配 print(match(re_str, 'mks结束的发就好为34')) # 匹配开头符合要求的
-
匹配对象
-
匹配对象.group()
---- 获取整个正则匹配到的内容re_str = r'((\d{2})([A-Z]{3}))' result = match(re_str, '23KLA失敬失敬') print(result) # <re.Match object; span=(0, 5), match='23KLA'> # 分组 指的() 一个括号代表一个分组 # 匹配对象.group(N) - 获取正则表达式第N个分组匹配到的内容 print(result.group()) # '23KLA' print(result.group(1)) # '23KLA' print(result.group(2)) # '23' print(result.group(3)) # 'KLA'
-
匹配对象.span()
— 获取整个正则匹配到的内容在原字符串中的位置信息(开始下标和结束下标)# 匹配对象.span() / 匹配对象.span(0) - 获取整个正则匹配到的内容在原字符串中的位置信息(开始下标和结束下标) # 匹配对象.span(N) - 获取正则表达式第N个分组匹配到的内容在原字符串中的位置信息 print(result.span()) print(result.span(3))
-
匹配对象.string
— 获取原字符串re_str = r'((\d{2})([A-Z]{3}))' result = match(re_str, '23KLA失敬失敬') print(result.string) # '23KLA失敬失敬'
-
-
-
查找相关方法
-
re.search(正则表达式, 字符串)
- 在字符串中搜索第一个满足正则表达式的字符串。如果找不到返回None,找到了返回匹配对象print(search(r'\d{3}', '试试234节省时间988开始时间210')) # 获取第一个遇到的值返回 # <re.Match object; span=(2, 5), match='234'>
-
re.findall(正则表达式, 字符串)
- 获取字符串中所有满足正则表达式的子串。返回值是列表,如果找不到返回空列表print(findall(r'\d{3}', '试试234节省时间988开始时间210')) # ['234', '988', '210'] print(findall(r'\d{3}[\u4e00-\u9fa5]', '试试234节省时间988开始时间210mn')) # ['234节', '988开'] print(findall(r'(\d{3})[\u4e00-\u9fa5]', '试试234节省时间988开始时间210mn')) # ['234', '988'] print(findall(r'\d{3}-[a-z]{2}', '啥时间233-ks试试,892-mk啥,sjs2912-op')) # ['233-ks', '892-mk', '912-op'] print(findall(r'(\d{3})-([a-z]{2})', '啥时间233-ks试试,892-mk啥,sjs2912-op')) # [('233', 'ks'), ('892', 'mk'), ('912', 'op')] print(findall(r'(\d[a-z]){3}', '是计算机上8m9l0b,s数据是8a0p1k')) # ['0b', '1k']
-
re.finditer(正则表达式, 字符串)
- 获取字符串中所有满足正则表达式的子串。返回一个迭代器,迭代器中的元素是匹配对象result = finditer(r'(\d{3})-([a-z]{2})', '啥时间233-ks试试,892-mk啥,sjs2912-op') # print([x.group() for x in result]) # ['233-ks', '892-mk', '912-op'] # print([x.group(1) for x in result]) # ['233', '892', '912'] print([x.group(2) for x in result]) # ['ks', 'mk', 'op']
-
re.sub(正则表达式, 字符串1, 字符串2)
- 将字符串2中所有满足正则的子串全部替换成字符串str1 = 'how are you? I am fine, Thank you!' result = sub(r'you', 'me', str1) print(result) # how are me? I am fine, Thank me! str1 = 'how are you? I am fine, Thank you!' result = sub(r'you|I', 'me', str1) print(result) # how are me? me am fine, Thank me! result = sub(r'傻[\s/,.\\]*[b瓜]|f\s*u\s*c\s*k|操', '*', r'我操, 你是傻 /b吗?F u c k') print(result)
-
re.split(正则表达式, 字符串)
- 将字符串中所有满足正则表达式的子串作为切割点对字符串进行切割result = split(r'[-+]', '试试-j234ss+skskj-健康是390福+世纪东2方看019计算机') print(result) result = split(r'\d+', '试试-j234ss+skskj-健康是390福+世纪东2方看019计算机') print(result)
-
-
-
转义符号和参数
-
转义符号 - 将在正则中有特殊功能或者意义的符号变成一个普通字符(如:
.
+
*
等)# \具有特殊意义的符号: \.、\+、\*、... re_str = r'\d{2}\.\d{2}' print(fullmatch(re_str, '23.34')) re_str = r'\\dabc\+' print(fullmatch(re_str, '\dabc+')) re_str = r'\(\d{2}\)' print(fullmatch(re_str, '(23)')) # 将独立存在具备特殊功能的符号放在[]里面,这个符号的功能会自动消失 # 特别注意符号在[]里面也有特殊功能的情况,比如:^、-、[、] re_str = r'\d{2}[.+?*(\-)|$^\]]\d{2}' print(fullmatch(re_str, '23]34'))
-
常用参数
-
忽略大小写(
re.I
)-
用法1:
r'(?i)正则表达式'
# 默认不忽略大小写 re_str = r'123[a-z]' print(fullmatch(re_str, '123k')) # <re.Match object; span=(0, 4), match='123k'> print(fullmatch(re_str, '123M')) # None # 用法一: r'(?i)正则表达式' re_str = r'(?i)123[a-z]' print(fullmatch(re_str, '123k')) # <re.Match object; span=(0, 4), match='123k'> print(fullmatch(re_str, '123M')) # <re.Match object; span=(0, 4), match='123M'>
-
用法2:参数
flags=re.I
# 用法二: re_str = r'123[a-z]' print(fullmatch(re_str, '123M', flags=I)) # <re.Match object; span=(0, 4), match='123M'>
-
-
单行匹配(
re.S
)-
用法1:
r'(?s)正则表达式'
""" 多行匹配(默认) - 表示任意字符的.不能和\n(换行符)进行匹配 单行匹配 - 表示任意字符的.可以和\n(换行符)进行匹配 """ # 用法一: re_str = r'(?s)abc.123' print(fullmatch(re_str, 'abc\n123')) # <re.Match object; span=(0, 7), match='abc\n123'>
-
用法2:参数
flags=re.S
# 用法二: re_str = r'abc.123' print(fullmatch(re_str, 'abc\n123', flags=S)) # <re.Match object; span=(0, 7), match='abc\n123'> re_str = r'(?is)abc.123' print(fullmatch(re_str, 'ABC\n123')) # <re.Match object; span=(0, 7), match='ABC\n123'> re_str = r'abc.123' print(fullmatch(re_str, 'ABC\n123', flags=I | S)) # <re.Match object; span=(0, 7), match='ABC\n123'>
-
-
-
作业
利用正则表达式完成下面的操作:
一、不定项选择题
- 能够完全匹配字符串
"(010)-62661617"
和字符串"01062661617"
的正则表达式包括(AB )
A.r"\(?\d{3}\)?-?\d{8}"
B. r"[0-9()-]+"
C.r"[0-9(-)]*\d*"
D.r"[(]?\d*[)-]*\d*"
- 能够完全匹配字符串“c:\rapidminer\lib\plugs”的正则表达式包括( AC )
A. “c:\rapidminer\lib\plugs”
B. “c:\rapidminer\lib\plugs”
C. “(?i)C:\RapidMiner\Lib\Plugs” ?i:将后面的内容的大写变成小写
D. “(?s)C:\RapidMiner\Lib\Plugs” ?s:单行匹配 - 能够完全匹配字符串“back”和“back-end”的正则表达式包括( ABC )
A. “\w{4}-\w{3}|\w{4}”
B. “\w{4}|\w{4}-\w{3}”
C. “\S±\S+|\S+”
D. “\w*\b-\b\w*|\w*” - 能够完全匹配字符串“go go”和“kitty kitty”,但不能完全匹配“go kitty”的正则表达式包括(D)
A. “\b(\w+)\b\s+\1\b”
B. “\w{2,5}\s*\1”
C. “(\S+) \s+\1”
D. “(\S{2,5})\s{1,}\1” - 能够在字符串中匹配“aab”,而不能匹配“aaab”和“aaaab”的正则表达式包括( BC)
A. “a*?b”
B. “a{,2}b”
C. “aa??b”
D. “aaa??b”
二、编程题
1.用户名匹配
要求: 1.用户名只能包含数字 字母 下划线
2.不能以数字开头
3.⻓度在 6 到 16 位范围内
def is_user(ueser_name):
re_str = '\D([0-9a-zA-Z_]){5,15}'
result = re.fullmatch(re_str, ueser_name)
if result:
print(f'{ueser_name}是合法的用户名!')
else:
print(f'{ueser_name}是不合法的用户名!')
is_user('z123456')
# z123456是合法的用户名!
- 密码匹配
要求: 1.不能包含!@#¥%^&*这些特殊符号
2.必须以字母开头
3.⻓度在 6 到 12 位范围内
def is_pw(pw):
re_str = '^[a-zA-Z]([^!@#¥%^&*]){5,15}'
result = re.fullmatch(re_str, pw)
if result:
print('密码符合规范!')
else:
print('密码不符合规范!')
is_pw('z12211') #密码符合规范!
- ipv4 格式的 ip 地址匹配
提示: IP地址的范围是 0.0.0.0 - 255.255.255.255
def is_ip(ip):
re_str = r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
# re_str = r'(\d{1}|[^0]\d{2,3})\.(\d{1}|[^0]\d{2,3})\.(\d{1}|[^0]\d{2,3})'
result = re.fullmatch(re_str, ip)
if result:
print(f'ip:{ip}符合规范!')
else:
print(f'ip:{ip}不符合规范!')
is_ip('0.0.0.0') #ip:0.0.0.0符合规范!
- 提取用户输入数据中的数值 (数值包括正负数 还包括整数和小数在内) 并求和
例如:“-3.14good87nice19bye” =====> -3.14 + 87 + 19 = 102.86
import re
def user_nums(str1):
sum2 = 0
re_str = r'\-?\d+\.?\d*'
result = re.findall(re_str, str1)
result1 = ' + '.join(result)
for i in result:
if '-' in i or '.' in i:
sum2 += float(i)
else:
sum2 += int(i)
print(result1, end='')
print(' =', sum2,)
print()
user_nums('-3.14good-87ni8ce19b9ye')
#-3.14 + -87 + 8 + 19 + 9 = -54.14
-
验证输入内容只能是汉字
def is_hanzi(str1): re_str = r'[\u4e00-\u9f05]*' result = re.fullmatch(re_str, str1) if result: print(f'您输入的:{str1} 都是汉字!') else: print(f'您输入的:{str1} 存在非汉字!') is_hanzi('啊啊啊啊啊啊啊') #您输入的:啊啊啊啊啊啊啊 都是汉字!
-
匹配整数或者小数(包括正数和负数)
def is_nums(str1): sum2 = 0 re_str = r'\-?\d+\.?\d*' result = re.findall(re_str, str1) print(result) user_nums('-3.14good-87ni8ce19b9ye98') # ['-3.14', '-87', '8', '19', '9', '98']
-
验证输入用户名和QQ号是否有效并给出对应的提示信息
要求:
用户名必须由字母、数字或下划线构成且长度在6~20个字符之间
QQ号是5~12的数字且首位不能为0 -
拆分长字符串:将一首诗的中的每一句话分别取出来
poem = ‘窗前明月光,疑是地上霜。举头望明月,低头思故乡。’
def spilt_Poetry(str1:str): re_str = r'[,。]' result = re.split(re_str, str1) print(result) spilt_Poetry('窗前明月光,疑是地上霜。举头望明月,低头思故乡') #['窗前明月光', '疑是地上霜', '举头望明月', '低头思故乡']