014-正则表达式

正则表达式

一、正则

正则表达式是一种可以让复杂的字符串问题变得简单的工具;正则不独属于python,几乎所有的高级语言都支持正则表达式;

二、python的re模块

re模块是python用来支持正则表达式的自带模块,模块中包含了所有和正则相关的函数

1、re模块相关函数
from re import 函数名
fullmatch(正则表达式,字符串)--判断正则表达式和指定的字符串是否完全匹配                            		匹配成功返回匹配对象,匹配失败返回空None
match(正则表达式,字符串) - 判断字符串开头是否符合正则表达式描述的规则
                        匹配成功返回匹配对象,失败返回空
search(正则表达式,字符串)--获取字符串中第一个能够和正则匹配成功的子串
                        找到匹配对象返回匹配对象,失败返回空
findall(正则表达式,字符串)--获取字符串中所有满足正则的子串,返回一个列表,列表中的元素都是字符串
     注意:如果正则表达式中有分组,会针对分组做自动捕获(只获取分组匹配到的结果)              
finditer(正则表达式,字符串)--获取字符串中所有满足正则的子串,返回一个迭代器,
						迭代器中的元素是匹配结果
split(正则表达式,字符串)--将字符串中所有满足正则的子串作为切割点进行切割
sub(正则表达式,新字符串,旧字符串) -- 将旧字符串中所有满足正则的子串都替换成新字符串
2、匹配对象
2.1 直接获取整个正则表达式对应的匹配结果
匹配对象.group()
2.2 手动捕获某个分组对应的结果
匹配对象.group(分组数)
2.3 获取匹配结果在原字符串中的位置
匹配对象.span()
3、参数
3.1 匹配忽略字母大小写
(?i)
from re import fullmatch
print(fullmatch(r'(?i)abc', 'aBc'))
3.2 单行匹配

单行匹配:匹配的时候’.‘能和换行’\n’进行匹配

多行匹配:匹配的时候’.‘不能和换行’\n’进行匹配

(?s)
from re import fullmatch
print(fullmatch(r'(?s)abc.123', 'abc\n123'))  # 单行匹配成功
print(fullmatch(r'abc.123', 'abc\n123'))  # 多行匹配 None
三、正则语法 - 匹配类符号
1、普通符号 - 在正则表达式中表示符号本身的符号
print(fullmatch(r'abc', 'abcdefr'))
2、. - 匹配任意字符
print(fullmatch(r'a.c', 'avc'))
3、\d - 匹配任意一个数字字符
print(fullmatch(r'a\dc', 'a1c'))
4、\D - 匹配任意一个非数字字符
print(fullmatch(r'a\Dc', 'a2c')) # None
5、\s - 匹配任意一个空白字符
print(fullmatch(r'a\sv', 'a v'))
print(fullmatch(r'a\sv', 'a\tv'))
6、\S - 匹配任意一个非空白字符
print(fullmatch(r'a\Sv', 'a\tv')) # None
7、\w : 匹配任意单个a-zA-Z0-9_汉字 或表示为[a-zA-Z0-9_]
8、\W : 匹配任意单个非a-zA-Z0-9_汉字别的任何 或表示为[^a-zA-Z0-9_]
9、[字符集] - 匹配字符集中的任意一个字符 字符集中的顺序任意
[abc]  -  匹配a或者b或者c
[abc\d] -   匹配a或者b或者c或任意数字 
[1-9]   -   匹配1-9中的任意一个数字 
[a-z]   -   匹配任意一个小写字母
[A-Z]   -   匹配任意一个大写字母
[a-zA-Z]-   匹配任意一个字母
[a-zA-Z\d_]-匹配字母数字或者下划线
[\u4e00-\u9fa5] -   匹配任意一个中文字符
注意:中括号[]中减号放在两个字符之间,表示区间,表示谁到谁(确定的方式是根据字符编码值的大小确定的)
     如果减号不在两个字符之间,就表示一个普通的符号
10、[^字符集] - 匹配不在字符集中的任意一个字符
print(fullmatch(r'a[^\u4e00-\u9fa5]b', 'a一b')) # None
print(fullmatch(r'a[^\u4e00-\u9fa5]b', 'avb'))  
# <re.Match object; span=(0, 3), match='avb'>
四、匹配次数
方法次数示例
*0次或者多次(任意次数)
*放在谁的后面就控制谁的次数
a* - 0个或者多个a
\d* - 0个或者多个数字
print(fullmatch(r'a*1', 'aaa1')) # 匹配成功
+1次或者多次(至少一次)print(fullmatch(r'a+122', '122')) # None
print(fullmatch(r'a+122', 'a122'))
0次或者1次print(fullmatch(r'a?122', 'a122')) print(fullmatch(r'a?122', '122'))
{}{M,N} M到N次
{M,} - 至少M/
{,N} - 最多N次
{N} - N次
练习
# 练习:写一个正则,判断输入的内容是否是一个合法的QQ号(长度是5~12位的数字,第一位不能是0)
qq=input('请输入qq号:')
print(bool(fullmatch(r'[1-9]\d{4,11}', qq)))
练习
# 练习:判断输入的内容是否是一个合法的标识符(由字母、数字下划线组成,数字不能开头)
bsf='_12fds'
print(bool(fullmatch(r'[a_zA-Z_][a-zA-Z\d_]*',bsf)))
五、贪婪和非贪婪

当匹配次数不确定的时候*、-、?、{M,N}、{M,}、{,N}
匹配模式分为贪婪和非贪婪两种,默认为贪婪的

贪婪和非贪婪:在匹配成功的时候有多种匹配结果,贪婪取最多次数对应的匹配结果,非贪婪取最少次数对应的匹配结果

贪婪模式:*、-、?、{M,N}、{M,}、{,N}
非贪婪模式:*?、-?、??、{M,N}?、{M,}?、{,N}?

注意:如果匹配结果只有一种可能,那么贪婪不贪婪的结果一样

# 结果  amb 、amb计算b 、 amb计算bxxb
print(match(r'a.+b', 'amb计算bxxbmn'))
#<re.Match object; span=(0, 9), match='amb计算bxxb'>
print(match(r'a.+?b', 'amb计算bxxbmn'))
# <re.Match object; span=(0, 3), match='amb'>
六、分组和分支
1、分组 - ()

1.1 将正则表达式中的一部分作为一个整体进行相关操作

from re import fullmatch,findall
# '12SV34DS23AC...'
str2='12SV34DS23AC'
print(fullmatch(r'(\d\d[A-Z]{2})+', str2))

1.2 重复 可以在正则表达式中通过 \M 来重复它前面的第M个分组的匹配结果

​ \M 只能重复在它之前出现的分组内容,无法重复在它之后出现的内容

from re import fullmatch
# 23m23 98k98  32f32
print(fullmatch(r'(\d{2})[a-z]\1', '23m23'))
# 23mgi=mgi23
print(fullmatch(r'(\d{2})([a-z]{3})=\2\1', '34hjl=hjl34'))

1.3 捕获 只获取正则表达式中的一部分匹配结果(分为手动和自动捕获两种)

from re import findall
message='我今年18岁,月薪50000元,身高180,体重78公斤,8块腹肌。每年交308元的腾讯会员费。房贷每月3008元,车贷每月2208元。'
result=findall(r'(\d+)元',message)
print(result)
2、分支
正则1|正则2|正则3|...  -  匹配可以和多个正则中任意一个匹配的字符串

注意:如果想要正则表达式中的一部分实现多选一的效果,变化的部分用分组表示

# a21b、amlsb  a开头b结尾 中间两个数字或者三个字母
from re import fullmatch,findall
print(fullmatch(r'a(\d{2}|[a-z]{3})b', 'a32b'))
print(fullmatch(r'a(\d{2}|[a-z]{3})b', 'avfgb'))
print(findall(r'a(\d{2}|[a-z]{3})b', 'avfgb'))
七、转义符号
1、转义符号

正则中的转义符号就是在本身具备特殊功能或者特殊意义的符号前加’',让这个符号变成一个普通符号

from re import fullmatch
result=fullmatch(r'\d+\.\d+','23.122')
print(result)
print(fullmatch(r'\([a-z]+\)', '(dfa)'))
2、[]里面的转义符号

单独存在有特殊意义的符号(+、*、?、.等),在[]中特殊意义会自动消失

from re import fullmatch
result = fullmatch(r'\d+[.+*?]\d+', '433?444')
print(result)

本身在中括号中有特殊功能的符号(-、^),如果表示普通符号必须加\

八、检测类符号

检测符号并不影响匹配,只是对匹配的符号进行筛选

1、 \b 检测是否是单词边界

单词边界:可以将两个单词区分开的符号都是单词边界,比如空白符号,英文标点符号,字符串开头和字符串结尾

print(fullmatch(r'abc\b mn', 'abc mn'))
2、 \B 检测是否不是单词边界
3、 ^ 检测是否是字符串开头
message='dfa123 四级的ewr235 ewr9=='
print(findall(r'^.{5}', message)) # ['dfa12']
4、 $ 检测是否是字符串结尾
message='dfa123 四级的ewr235 ewr9=='
print(findall(r'.{5}$', message)) # ['wr9==']

正则表达式练习题

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

    A. r"\(?\d{3}\)?-?\d{8}"
    B. r"[0-9()-]+"
    C. r"[0-9(-)]*\d*" #(-)是一个整体,代表()
    D.r"[(]?\d*[)-]*\d*"

  2. 能够完全匹配字符串"back"和"back-end"的正则表达式包括(ABCD )
    A. r'\w{4}-\w{3}|\w{4}' # \w 匹配任意单个a-zA-Z0-9_汉字
    B. r'\w{4}|\w{4}-\w{3}'
    C.r'\S+-\S+|\S+' #\S 非空字符
    D. r'\w*\b-\b\w*|\w*'

  3. 能够完全匹配字符串"go go"和"kitty kitty",但不能完全匹配“go kitty”的正则表达式包括(AD)
    A.r'\b(\w+)\b\s+\1\b' # \s 匹配任何一个空白字符
    B. r'\w{2,5}\s*\1' # 没有分组 正确写法 :r'(\w{2,5})\s*\1'
    C. r'(\S+) \s+\1' # 中间有空格 正确写法 :r'(\S+)\s+\1' 或者 r'(\S+) +\1'
    D. r'(\S{2,5})\s{1,}\1'

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

二、编程题

1.用户名匹配

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

​ 2.不能以数字开头

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

from re import fullmatch
name='f324_dska2'
result=fullmatch(r'[a-zA-Z_][a-zA-Z0-9_]{5,15}', name)
# result=fullmatch(r'[a-zA-Z_][a-zA-Z\d_]{5,15}', name)
if result:
    print('合法')
else:
	print('不合法')
  1. 密码匹配

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

​ 2.必须以字母开头

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

from re import fullmatch
password = 'sdfs213'
result=fullmatch(r'[a-zA-Z][^!@#$%^&*]{5,11}', password)
if result:
    print(password,'合法')
else:
    print(password,'不合法')
  1. ipv4 格式的 ip 地址匹配
    提示: IP地址的范围是 0.0.0.0 - 255.255.255.255
from re import fullmatch
ip = '255.256.255.255'
# 分段 从数字的不同位数考虑 0-9  10-99 100-199 200-249 250-255
result=fullmatch(r'((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])',ip)
if result:
    print(ip,'合法')
else:
    print(ip,'不合法')
  1. 提取用户输入数据中的数值 (数值包括正负数 还包括整数和小数在内) 并求和
例如:“-3.14good87nice19bye” =====> -3.14 + 87 + 19 = 102.86
from re import findall
num='-3.14good87nice19bye'
list1=findall(r'-?\d+\.?\d+',num)
total=sum(float(i) for i in list1)
print(total)  # 102.86
  1. 验证输入内容只能是汉字
from re import fullmatch
text=input('请输入内容:')
print(fullmatch(r'[\u4e00-\u9fa5]', text))
  1. 匹配整数或者小数(包括正数和负数)
from re import fullmatch
# 整数正则 [-+]?(0|[1-9]\d*)
# 小数正则 [-+]?(0|[1-9]\d*)\.\d+
# 数字正则  [-+]?(0|[1-9]\d*)(\.\d+)?
num=input('请输入数字:')
print(fullmatch(r'[-+]?(0|[1-9]\d*)(\.\d+)?',num))
  1. 验证输入用户名和QQ号是否有效并给出对应的提示信息

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

from re import fullmatch
name='lili_012'
QQ='1532141423'
print(fullmatch(r'[a-zA-Z0-9_]{6,20}', name))
print(fullmatch(r'[1-9]\d{4,11}', QQ))
  1. 拆分长字符串:将一首诗的中的每一句话分别取出来

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

from re import split
poem = '窗前明月光,疑是地上霜。举头望明月,低头思故乡。'
result=split(r',|。',poem)
for i in result:
    print(i)
# 窗前明月光
# 疑是地上霜
# 举头望明月
# 低头思故乡
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

兮知

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值