############### re模块 ################
正则表达式的规则:
# re模块
# 正则表达式,就是做字符串匹配的,在re模块出现之前就有这个正则表达式了,任何语言都有这个,
# 要使用Python来操作正则表达式,就要使用到re模块了,
# # 正则表达式只和字符串匹配有关系,和其他的数据类型没有关系, # 应用非常的广泛,
# 比如手机号,
# 比如身份证号
# 比如邮箱, # 实现手机号的格式验证:
# 不使用正则表达式,使用Python代码也是可以实现的
# while True:
# phone_number = input('please input your phone number : ')
# if len(phone_number) == 11 \
# and phone_number.isdigit()\
# and (phone_number.startswith('13') \
# or phone_number.startswith('14') \
# or phone_number.startswith('15') \
# or phone_number.startswith('18')):
# print('是合法的手机号码')
# else:
# print('不是合法的手机号码') # 使用正则表达式,会把这个过程变的非常的简洁
# 正则表达式在处理字符串匹配上有非常的优势
# import re
# phone_number = input('please input your phone number : ')
# if re.match('^(13|14|15|18)[0-9]{9}$',phone_number):
# print('是合法的手机号码')
# else:
# print('不是合法的手机号码') # 正则表达式的规则:
##################################################################
# 字符组: # 字符组:[字符组] 一个字符串只能是表示一位
# 正则 待匹配 匹配结果
# [0123456789] 8 True
# [0123456789] a False # 注意这种写法,一般不这么写,但是这么写是可以的,你要知道
# [0 - 9] 7 True # 所以匹配所有的数字就是这么写
# [a-z] s True # 匹配所有的小写字母
# [A-Z] S True # 匹配所有的大写字母
# [0-9a-zA-Z] e True # 匹配大小写字母和所有的数字, ##################################################################
# 元字符 # . 匹配除换行符以外的任意字符
# \w 匹配字母或数字或下划线,word的意思,
# \W 匹配非字母或数字或下划线
# \s 匹配任意的空白符,space的意思
# \S 匹配非空白符
# \d 匹配数字,digit的意思
# \D 匹配非数字
# 注意你把上面的两对放入一个字符组里面去,匹配的都是全局,[\w\W] [\s\S],但是我们不这么用 # \n 匹配一个换行符,
# \t 匹配一个制表符,就是一个tab键, # \b 匹配一个单词的结尾 # 这个不常用, # ^ 匹配字符串的开始
# $ 匹配字符串的结尾
# ^[a-z]$ 这就是表示只能有一个字符,并且是小写,
# 一个字符组只能匹配一个字符, # a|b 匹配字符a或字符b 主要是记住这个 | 这是或的关系, # () 匹配括号内的表达式,也表示一个组
# [...] 匹配字符组中的字符
# [^...] 匹配除了字符组中字符的所有字符,前面加了^ 这是非的意思, # -----------------------
# 你学了上面的写着字符组和元字符,那么你所有的单个字符都可以匹配了,
# 但是匹配一个手机号你还是不行,
# [\d\d\d\d\d\d\d\d\d\] 不能是这样, ####################################################################
# 量词 # 用法说明
# * 重复零次或更多次,\d*不管有多少的数字都能匹配上,这种叫做贪婪匹配,但是遇到一个非数字就停止了,
# + 重复一次或更多次,\d+这种也是贪婪的,但是不能是零次
# ? 重复零次或一次,\d?,
# {n} 重复n次,,这种可以指定重复次数,
# {n,} 重复n次或更多次
# {n,m} 重复n到m次
# 所有的量词都要匹配到元字符的后面,而且要紧贴着 # 举例:
# 海盐海草海梅
# 怎么把所有的匹配出来:海. 记住这个点还是代表的一个字符,
# 怎么只匹配到第一个:^海. # 举例:
# 李杰和李莲英和李二棍子
# 怎么把所有的人名都匹配出来:
# 各种错误匹配解析:
# 第一种:李. 不行
# 第二种:李.? ?号只能匹配李后面0个或1个字符,贪婪匹配,就是1个,
# 第三种:李.* 匹配li后面的0个或多个字符,贪婪匹配,后面越多越好,
# 第四种:李.+ 匹配li后面的1个或多个字符,贪婪匹配,后面越多越好,
# 第五种:李.{1,2} {1,2}匹配1到2次任意字符,会匹配到三个,这种也是贪婪匹配,所以以2为主
# 第六种:李.{1,2}? # 这种加一个问号就是一个非贪婪匹配了,也叫做惰性匹配,
# 所以注意了,问好有两个用法了,
# 第七种:李.*? 这种加了问号变成非贪婪匹配,就变成了,以0个了为基准了,惰性匹配, # 正确的匹配,
# 第一种:李[^和]*,这种是可以的
# 第二种:李[杰莲英二棍子]* ##################################################################
# 分组:
# 使用()
# 上面我们看到如果想要使用量词,只能约束和他紧邻的一个字符组,如果我想要约束多个怎么办
# 就是使用括号把多个字符放入一个括号,这就是分组,然后约束就是约束这个组了, # 身份证号码:
# 是一个长度为15或18个字符的字符串,
# 如果是15位则全部是数字组成,首位不能为0;
# 如果是18位,则前17位全部是数字,末位可能是数字或x, # 第一种: ^[1-9]\d{13,16}[0-9x]$
# 分析这种是^[1-9],是首位不能为0;\d{13,16} 是约束中间的,[0-9x]$末位可能是数字或x,
# 但是有问题,就是这个\d{13,16} ,这个弹性太大,只能是15,18,不能是16,17位的
# 而且即使15位也是可以x结尾,这是不行的, # 第二种:^[1-9]\d{14}(\d{2}[0-9x])?$
# 分析:^[1-9],\d{14},(\d{2}[0-9x])?$
# 关键是第三部分,最后一个分组,要么都匹配上,要么就是没有,很巧妙
# 这就是一个成功的了 # 第三种:^([1-9]\d{16}[0-9x]|[1-9]\d{14})$
# 分析:[1-9]\d{16}[0-9x] [1-9]\d{14}
# 这种很巧妙,就是封成了1组,但是中间是或,就是写了两种,#
# 一定注意把长的规则放到前面,不能把短的规则放到前面,,
# 这也是一个成功的, ####################################################################
# 转义符
# 如果就是想要匹配\d怎么办?
# 就需要转译,\\d,这种就是转义了,
# 如果我想要匹配: \\d 怎么办,就要使用\\\\d,每一个反斜杠都要 转义, # 很麻烦,怎么办?
# r'\\n' r'\n' 在字符串之前加r,让整个字符串不转义 #####################################################################
# 贪婪匹配,一直往后匹配
# 加问号是惰性匹配,
# *? 重复任意次,但尽可能少重复
# +? 重复1次或更多次,但尽可能少重复
# ?? 重复0次或1次,但尽可能少重复
# {n,m}? 重复n到m次,但尽可能少重复
# {n,}? 重复n次以上,但尽可能少重复 # .*?的用法
# . 是任意字符
# * 是取 0 至 无限长度
# ? 是非贪婪模式。
# 何在一起就是 取尽量少的任意字符,一般不会这么单独写,他大多用在:.*?x
# 就是取前面任意长度的字符,直到一个x出现 #######################################################################
# 上面就是正则的规则了,学会了这些就够你使用的了
# 需要灵活使用这些,这个规则是不会改变的,
re模块的用法:
# re模块
import re #############################################
# ret = re.findall("[a-z]+","abc aaa an")
# print(ret) # ['abc', 'aaa', 'an'],这是放到列表中,
# # [a-z]+这就是第一个是a-z,后面是匹配任意的1到多次, ############################################
# ret = re.search("[a-z]+","abc aaa an").group()
# print(ret) # ['abc', 'aaa', 'an'],这是放到列表中,
# 这个search是找到一个就返回,而且一定要使用group才会出结果,
# 如果结果找不到就会报错,报错是因为结果是none所以调用group会报错的, # 一般是这么用的
# # ret = re.search("[a-z]+","abc aaa an")
# ret = re.search("t","abc aaa an")
# if ret:
# ret = ret.group()
# print(ret)
# else:
# print("找不到") ##############################################
# match是从头匹配,如果匹配上就会返回一个变量,然后使用group显示,
# 匹配不上,就是none使用group会报错,
# 同search,不过尽在字符串开始处进行匹配
# ret = re.match("aaa","abc aaa an")
# if ret:
# ret = ret.group()
# print(ret)
# else:
# print("找不到") #####################################################
# ret = re.split("[ab]","abcd")
# print(ret) # ['', '', 'cd']
# 为什么是这个结果,因为是按照a和b分割,先按照a,然后按照b
# 这个不太常用 ###################################################
# ret = re.sub("\d","H","eefeflef4fefe4",1)
# print(ret)
# 这个方法是替换,把第一个参数替换成为第二个参数,文本就是第三个,替换次数就是第四个参数,不写的还就是全部替换, ###################################################
# ret = re.subn("\d","H","eefeflef4fefe4",1)
# print(ret) # ('eefeflefHfefe4', 1)
# 这个方法不只是把替换的结果返回来,还会把替换的次数给你返回回来, ###################################################
# 如果你想要把一个正则规则反复使用,或者这个规则非常长的时候可以使用一个方法 # obj = re.compile("\d{3}") # 可以反复使用这个正则,
# ret = obj.search("abc123afdfadsf")
# print(ret.group())
# ret = obj.search("abcafdfadsf456")
# print(ret.group()) #####################################################
# 如果返回的结果非常的多,可以使用迭代器,
# import re
# ret = re.finditer('\d', 'ds3sy4784a') # finditer返回一个存放匹配结果的迭代器
# print(ret) # <callable_iterator object at 0x10195f940>
# print(next(ret).group()) # 查看第一个结果
# print(next(ret).group()) # 查看第二个结果
# print([i.group() for i in ret]) # 查看剩余的所有结果 ######################################################## # ret = re.search("^[1-9]\d{14}(\d{2}[0-9x])?$","370883199908181818")
# print(ret.group())
# print(ret.group(1)) # 这是取值第一个分组,现在就是只有一个分组,818
# 如果你就知道为什么要使用group了, ######################################################## # import re
#
# ret = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com')
# print(ret) # ['oldboy'] 这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可
#
# ret = re.findall('www.(?:baidu|oldboy).com', 'www.oldboy.com')
# print(ret) # ['www.oldboy.com']
# # 这是问号的第三个用法了, ##############################################
ret=re.split("\d+","eva3egon4yuan")
print(ret) # 结果 : ['eva', 'egon', 'yuan'] ret=re.split("(\d+)","eva3egon4yuan")
print(ret) # 结果 : ['eva', '3', 'egon', '4', 'yuan']
# 在匹配部分加上()之后所切出的结果是不同的,
# 没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项,
# 这个在某些需要保留匹配部分的使用过程是非常重要的。
# 这个还是非常的有用的,
############################################
例题:
# 字符串a = "not 404 found 张三 99 深圳",每个词中间是空格,用正则过滤掉英文和数字,最终输出"张三 深圳"
a = "not 404 found 张三 99 深圳"
list1 = a.split(" ")
print(list1) # ['not', '404', 'found', '张三', '99', '深圳']
import re
ret = re.findall("\d+|[a-zA-Z]+",a)
for i in ret:
if i in list1:
list1.remove(i)
print(list1) # ['张三', '深圳']
new_str = " ".join(list1)
print(new_str) # 张三 深圳
###########################################
###########################################