正则表达式
一:正则匹配类符号
1、什么是正则(正则表达式)
正则是一种用来处理文本数据的一种工具。(一般用于处理复杂的文本问题)
2、正则语法 - 用不同的符号来描述字符串的规则
1)匹配类符号
2)检查类符号
3)控制次数的符号
4)分组和分支
5)其他常用参数
fullmatch(正则表达式,字符串) - 检测字符串是否符合正则表达式描述的规则,如果不符合返回None
r ‘正则表达式’ - Python “正则表达式” - oc/python /正则表达式/ – js
3、匹配类符号 - 一个符号对应字符串的一个字符
1)普通字符 - 特殊符号以外的字符就是普通字符
普通字符在正则中表示这个符号本身
re_str='abc' # 需要一个长度为3的字符串,并且第一个字符是a,第二个字符是b,第三个字符是c
print(fullmatch(re_str,'abc'))
2). - 匹配任意一个字符
re_str='a.c' # 需要一个长度为3字符串,并且第一个字符是a,第三个字符是c,中间是任意字符
print(fullmatch(re_str,'ahc'))
re_str='..ab' # 需要一个长度为4字符串,ab前面任意字符
print(fullmatch(re_str,'jkab'))
3) \d - 匹配任意一个数字字符
re_str=r'ab\d' # 一个长度为3的字符串,ab后面是任意数字
print(fullmatch(re_str,'ab9'))
5) \s - 匹配任意一个空白字符
空白字符 - 空格、\t 、\n
re_str1=r'123\sabc'
print(fullmatch(re_str1,'123\nabc'))
print(fullmatch(re_str1,'123\tabc'))
- \D、\S
\D - 匹配任意一个非数字字符
\S – 匹配任意一个非空白字符
print(fullmatch(r'abc\S123\D','abcM123='))
print(fullmatch(r'abc\S123\D','abcM1239')) # None
print(fullmatch(r'abc\S123\D','abc好123t'))
7)[字符集] - 匹配字符集中的任意一个字符
[ab12] - 匹配字符可以是a、b、1、2中任意一个字符
[ab\d]、[\dab]、[a\db]、[ab0123456789] - 匹配a、b或者0~9中任意一个字符
[0-9] - 匹配0~9中任意一个字符
[5-9] - 匹配5到9中任意一个字符
[a-z] - 匹配任意一个小写字母
[A-Z] - 匹配任意一个大写字母
[a-zA-Z] - 匹配任意一个字母
[a-zA-Z\d] - 匹配任意一个字母、数字
[\u4e00-\u9fa5] - 匹配任意一个中文
注意:如果[]中-在两个字符之间表示范围,如果不在两个字符之间,它具备特殊功能就表示符号本身
不能随便加空格
re_str1=r'a[xyz]b'
print(fullmatch(re_str1,'azb'))
print(fullmatch(re_str1,'axb'))
print(fullmatch(re_str1,'ayb'))
print(fullmatch(r'abd[2-5]','abd2'))
print(fullmatch(r'abc[\u4e00-\u9fa5]','abc就'))
# print(fullmatch(r'abc[z-a]','abcw')) # 报错
print(fullmatch(r'[-ac]123','a123'))
8)1 - 匹配除了字符集以外的任意一个字符
print(fullmatch(r'[^a]123','a123')) # None
print(fullmatch(r'[^a]123','m123'))
注意[]里面,只有放在最前面才有特殊功能,其他位置都表示本身
print(fullmatch(r'[^a-zA-Z]123','哭123'))
print(fullmatch(r'[a-z^]123','^123'))
二:检查类符号
检测类符号在正则中不影响字符串长度,他们的作用是在匹配成功以后检测检测类符号所在位置是否符合要求
1、\b - 检测是否是单词边界
单词边界 - 凡是能够把两个单词区分开的所有的符号,主要有:空白,标点符号,字符串开头和字符串结尾
re_str=r'abc.\b123'
print(fullmatch(re_str,'abc 123'))
re_str=r'abc.\b123'
print(fullmatch(re_str,'abcm123')) # None
- \B - 检测是否不是单词边界
str1='shuju,890,ssjjs323hh34hhh 922 hsuashu8ffjj283'
result=findall(r'\B\d+\B',str1)
print(result) # ['9', '323', '34', '2', '8', '28']
- ^ - 检测是否是字符串开头([]外面)
- $ - 检测是否是字符串结尾([]外面)
re_str = r’^\dabc’
re_str = r'\dabc$'
print(findall(re_str, '7abc啥时间2abc数据9abc是6abc'))
三:匹配次数
1、* - 匹配0次或多次
a* - 匹配任意多个a
.* - 匹配0个或者多个任意字符
\d* - 相当于任意多个\d
[xyz]* - 相当于任意多个[xyz]
re_str=r'a*123'
print(fullmatch(re_str,'123'))
print(fullmatch(re_str,'aaaa123'))
re_str=r'.*123'
print(fullmatch(re_str,'123'))
print(fullmatch(re_str,'sw123'))
re_str=r'\d*abc'
print(fullmatch(re_str,'1abc'))
re_str=r'[xyz]*abc'
print(fullmatch(re_str,'xxyyabc'))
2、+ - 1次或者多次
3、? - 0次或1次
4、{}
{N} - N次
{M,N} - 匹配M~N次
{,N} - 匹配0~N次(最多N次)
{M,} 匹配至少N次
print(fullmatch(r'\d{3}abc{5}','212abccccc'))
print(fullmatch(r'\d{3,5}abc{5}','2124abccccc'))
print(fullmatch(r'\d{,3}abc{5}','21abccccc'))
print(fullmatch(r'\d{3,}abc{5}','2332abccccc'))
练习:写一个正则表达式能够判断输入的手机号码是合法:1)长度11位 2)都是数字 3)第一位必须是1 4)第二位从3~9
def is_tel(tel:str):
re_str1=r'1[3-9]\d{9}'
result=fullmatch(re_str1,tel)
if result:
print(f'{tel}是合法的手机号')
else:
print(f'{tel}不是合法手机号')
5、贪婪和非贪婪
贪婪和非贪婪模式是在匹配不确定次数的时候才会出现:*、+、?、{M,N},{,N},{M,}
贪婪和非贪婪:在能匹配成功的情况下,如果对应的匹配的次数有多种,贪婪模式选最多的那个次数,非贪婪选最少的那个次数
贪婪:、+、?、{M,N},{,N},{M,}都是贪婪的
非贪婪:?、+?、??、{M,N}?,{,N}?,{M,}?
# 贪婪
re_str=r'a.+b'
print(search(re_str,'摔坏amnbxyzb和hi哦我偶尔违法及范围')) # <re.Match object; span=(2, 10), match='amnbxyzb'>
# 非贪婪
re_str=r'a.+?b'
print(search(re_str,'摔坏amnbxyzb和hi哦我偶尔违法及范围')) # <re.Match object; span=(2, 6), match='amnb'>
四:分组和分支
分组 - ()
应用1:将正则表达式中的一部分()用括号括起来表示一个整体,然后进行整体相关操作
应用2:通过\M来重复前面第M个分组匹配到的内容
应用3:捕获(获取结果的时候只取某个分组的对应的内容)
# hu78kk56kk90
re_str=r'([a-zA-Z]{2}\d\d){3}'
print(fullmatch(re_str,'hu78kk56kk90'))
# 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})([A-Z]{3})\1{2}\2'
print(fullmatch(re_str,'12MNA1212MNA'))
re_str=r'[a-z]\d{3}'
result=findall(re_str,'kjj234你好a839shsh9901沙河--234卡卡238')
print(result) # ['j234', 'a839', 'h990']
re_str=r'[a-z](\d{3})'
result=findall(re_str,'kjj234你好a839shsh9901沙河--234卡卡238')
print(result) # ['234', '839', '990']
2、分支 - |
正则1|正则2
| 相当于或者
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,'abc123'))
re_str=r'abc\d{2}|ab{2}|mn'
print(fullmatch(re_str,'abc12'))
print(fullmatch(re_str,'abb'))
print(fullmatch(re_str,'mn'))
五:re模块
1.compile(正则表达式) - 创建一个正则表达式对象
re_obj=compile(r'\d{3}')
print(fullmatch(r'\d{3}','345'))
print(re_obj.fullmatch('234'))
2、匹配相关方法
1)fullmatch(正则表达式,字符串) - 完全匹配,判断整个字符串是否符合正则表达式的描述的规则,如果不符合返回None,如果符合返回匹配对象
2)match(正则表达式,字符串) - 匹配开头,判断字符串开头是否符合正则表达式的描述的规则,如果不符合返回None,如果符合返回匹配对象
re_str=r'[a-z]{3}'
print(fullmatch(re_str,'hsm'))
print(match(re_str,'mas就说'))
3)匹配对象
re_str=r'[a-z]{3}'
print(match(re_str,'mas就说ddd'))
a、
匹配对象.group() - 获取整个正则表达式匹配到的内容
匹配对象.group(N) - 获取正则表达式第N个分组匹配到的内容
re_str=r'(\d{2})([a-z]{3})'
result=match(re_str,'23klm帮帮忙')
print(result.group()) # '23klm'
print(result.group(1)) # '23'
print(result.group(2)) # 'klm'
re_str=r'((\d{2})([a-z]{3}))'
result=match(re_str,'23klm帮帮忙')
print(result.group()) # '23klm'
print(result.group(1)) # '23klm'
print(result.group(2)) # '23'
print(result.group(3)) # 'klm'
c 匹配对象.string - 获取原字符串
print(result.string) # '23klm帮帮忙'
3、查找相关方法
1)search(正则表达式,字符串) - 在字符串中查找第一个满足正则表达式的字符串,如果找不到返回None,找到返回匹配对象
print(search(r'\d{3}','jhkk23423njnj210')) # <re.Match object; span=(4, 7), match='234'>
2)findall(正则表达式,字符串) - 获取字符串的所有满足正则表达式的子串,返回值是列表,如果找不到返回空列表
print(findall(r'\d{3}','jhkk23423njnj210')) # ['234', '210']
print(findall(r'\d{3}[\u4e00-\u9af5]','滑到呼呼的234呼呼大345家世界219mm')) # ['234呼', '345家']
print(findall(r'(\d{3})[\u4e00-\u9af5]','滑到呼呼的234呼呼大345家世界219mm')) # ['234', '345']
print(findall(r'(\d[a-z]){3}','滑到呼呼的2m1n1n呼呼大345家世界8o8p1k')) # ['1n', '1k']
3)finditer(正则表达式,字符串) - 获取字符串中所有满足正则表达式的子串,返回一个迭代器,迭代器中的元素是匹配对象
# print([x.group() for x in result]) # ['233-kl', '892-mk', '277-op']
print([x.group(1) for x in result]) # ['233', '892', '277']
print([x.group(2) for x in result]) # ['kl', 'mk', 'op']
4)sub(正则表达式,字符串1,字符串2) - 将字符串2中所有满足正则的子串全部替换成字符串1
str1='hwo are you? I am file,Thank you!'
result=sub(r'you','me',str1)
print(result) # hwo are me? I am file,Thank me!
result=sub(r'you|I','me',str1)
print(result) # hwo are me? me am file,Thank me!
5、split(正则表达式,字符串) - 将字符串中所有满足正则表达式的子串作为切割点对字符进行切割
result=split(r'[-+]','sjsjs+加速卡萨-的江口街道+家科技的')
print(result) # ['sjsjs', '加速卡萨', '的江口街道', '家科技的']
result=split(r'\d+','sjsjs+加速340卡萨-的江2口街道+家013科技的')
print(result) # ['sjsjs+加速', '卡萨-的江', '口街道+家', '科技的']
六:转义符号和参数
1、转义符号 - 将在正则中有特殊功能或者意义的符号变成一个普通字符
\具有特殊意义的符号:.、+、*……
re_str=r'\d{2}\.\d{2}'
print(fullmatch(re_str,'23.24'))
re_str=r'\\dabc'
print(fullmatch(re_str,'\dabc'))
re_str=r'\(\d{2}\)'
print(fullmatch(re_str,'(23)')) # <re.Match object; span=(0, 4), match='(23)'>
将独立存在具备特殊功能的符号放在[]里面,这个符号的功能会自动消失
特别注意符号在[]里面有特殊功能的情况,比如:^、-、[、]
re_str=r'\d{2}[.+?()|$-^]\d{2}'
print(fullmatch(re_str,'23$23')) # <re.Match object; span=(0, 5), match='23$23'>
2、常用参数
默认不忽略大小写
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
用法1:r’(?i)正则表达式’
re_str=r'(?i)123[a-z]'
print(fullmatch(re_str,'123h')) # <re.Match object; span=(0, 4), match='123h'>
print(fullmatch(re_str,'123M')) # <re.Match object; span=(0, 4), match='123M'>
用法2:
re_str=r'123[a-z]'
print(fullmatch(re_str,'123M',flags=I)) # <re.Match object; span=(0, 4), match='123M'>
2)单行匹配
多行匹配(默认) - 表示任意字符的.不能和\n(换行符)进行匹配
单行匹配 - 表示任意字符的.能和\n(换行符)进行匹配
re_str=r'abc.123'
print(fullmatch(re_str,'abc\n123')) # None
用法1:
re_str=r'(?s)abc.123'
print(fullmatch(re_str,'abc\n123')) # <re.Match object; span=(0, 7), match='abc\n123'>
用法2:
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'(?si)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"
的正则表达式包括(a/ b)
A.r"\(?\d{3}\)?-?\d{8}"
B. r"[0-9()-]+"
C.r"[0-9(-)]*\d*"
D.r"[(]?\d*[)-]*\d*"
- 能够完全匹配字符串“c:\rapidminer\lib\plugs”的正则表达式包括( a)
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”的正则表达式包括(a/b/c )
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”的正则表达式包括( b、c)
A. “a*?b”
B. “a{,2}b”
C. “aa??b”
D. “aaa??b”
二、编程题
1.用户名匹配
要求: 1.用户名只能包含数字 字母 下划线
2.不能以数字开头
3.⻓度在 6 到 16 位范围内
from re import *
def user_name_match(use_name:str):
re_str=r'([a-zA-Z_])([a-zA-Z_\d]){5,15}'
result=fullmatch(re_str,use_name)
if result:
print('用户名匹配')
else:
print('用户名不匹配')
user_name_match('_jjjd111')
- 密码匹配
要求: 1.不能包含!@#¥%^&*这些特殊符号
2.必须以字母开头
3.⻓度在 6 到 12 位范围内
def pw_match(pw:str):
re_str=r'[a-zA-Z]([a-zA-Z\d]){4,10}[^!@#$%\^\*\u4e00-\u9af5]'
result=fullmatch(re_str,pw)
if result:
print('密码匹配')
else:
print('密码不匹配')
pw_match('y1ttni111')
- ipv4 格式的 ip 地址匹配
提示: IP地址的范围是 0.0.0.0 - 255.255.255.255
def ip_match(ip1):
re_str=r'(\d|\d[1-9]\d|\d[1]\d[1]\d{2}|\d[2]\d[0-4]\d|\d[2]\d[5]\d[0-5])(\.)\1\2\1\2\1'
result=fullmatch(re_str,ip1)
if result:
print('ip地址匹配')
else:
print('ip地址不匹配')
ip_match('0.0.0.0')
- 提取用户输入数据中的数值 (数值包括正负数 还包括整数和小数在内) 并求和
例如:“-3.14good87nice19bye” =====> -3.14 + 87 + 19 = 102.86
def extract_sum1(str1:str):
sum1=0
re_str=r'[-\d\.]+'
result=findall(re_str,str1)
for x in result:
x1=float(x)
sum1+=x1
print(sum1)
extract_sum1('-3.14good87nice19bye')
- 验证输入内容只能是汉字
def verify_chinese(str1:str):
re_str = r'[\u4e00-\u9af5]+'
result=fullmatch(re_str,str1)
if result:
print('是汉字')
else:
print('不是汉字')
verify_chinese('汉字')
- 匹配整数或者小数(包括正数和负数)
def number(str1:str):
re_str = r'[-\d\.]+'
result = fullmatch(re_str, str1)
if result:
print('匹配整数或者小数')
else:
print('不匹配整数或者小数')
number('-12.1')
-
验证输入用户名和QQ号是否有效并给出对应的提示信息
要求:
用户名必须由字母、数字或下划线构成且长度在6~20个字符之间
QQ号是5~12的数字且首位不能为0def user_name_match(use_name:str,qq:str): re_str=r'([a-zA-Z_\d]){6,20}' re_str1=r'\d[1-9]\d{3,10}' result=fullmatch(re_str,use_name) result1=fullmatch(re_str1,qq) if result: print('用户名匹配') else: print('用户名不匹配') if result1: print('qq匹配') else : print('qq不匹配') user_name_match('111111111111111111111','12344')
-
拆分长字符串:将一首诗的中的每一句话分别取出来
poem = ‘窗前明月光,疑是地上霜。举头望明月,低头思故乡。’
poem ='窗前明月光,疑是地上霜。举头望明月,低头思故乡。'
result=split(r'[,。]',poem)
for x in result:
print(x)