python 正则表达式

python 正则表达式

正则表达式是一个特殊的字符序列,可以方便的价差一个字符串是否与某个模式串匹配。
pythonre包拥有全部的正则表达式功能。


1、正则表达式语法

语法 含义
[ABC] 匹配字符串中的所有ABC
[^ABC] 匹配字符串所有的非ABC
[A-Z] 匹配所有的A-Z大写字母
\s 空白字符,包括换行
\S 匹配非空白字符,不包括换行
\w 匹配字母,下划线,数字,\w等价于 A-Za-z0-9_
限定符 含义
* 表示前面的子表达式出现0次或者多次,abc*d可以匹配abd,abcd,abccd
+ 表示前面的子表达式出现1次或者多次
? 表示前面的子表达式出现1次或者0次
. 匹配除\n之外的任何字符
.* 贪婪模式,可以匹配最长的,比如a.*b会匹配aababazzzzzzbbbbbbb等,可以匹配以a开头,以b结尾的所有串
.*? 懒惰模式,非贪婪模式,a.*?会匹配aababacb,即以a开头,以b结尾最短的,中间可以没有。就是找到一个a,然后再找到第一个b就结束
.+? 懒惰模式,可以匹配以a开头,以b结尾,中间必须有的字符串,ab是不可以的
() 一个正则表达式开始结束的位置
{} 表示限定符的开始结束,比如o{2}可以匹配food中的ooo{2,5}表示o出现2次到5次,[1-9][0-9]{0,1}匹配0-99的两位数
| 两项之间做个选则
定位符 含义
^ 字符串开始的位置
$ 匹配字符串结尾的位置
\b 单词边界,字与空格间的位置
最简单的正则表达式是普通字符串,可以匹配自身
'[pjc]ython'可以匹配'python'、'jython'、'cython'
'[a-zA-Z0-9]'可以匹配一个任意大小写字母或数字
'[^abc]'可以一个匹配任意除'a'、'b'、'c'之外的字符
'python|perl'或'p(ython|erl)'都可以匹配'python'或'perl'
子模式后面加上问号表示可选。r'(http://)?(www\.)?python\.org'只能匹配'http://www.python.org'、'http://python.org'、'www.python.org'和'python.org'
'^http'只能匹配所有以'http'开头的字符串
(pattern)*:允许模式重复0次或多次
(pattern)+:允许模式重复1次或多次
(pattern){m,n}:允许模式重复m~n次


'(a|b)*c':匹配多个(包含0个)a或b,后面紧跟一个字母c。
'ab{1,}':等价于'ab+',匹配以字母a开头后面带1个至多个字母b的字符串。
'^[a-zA-Z]{1}([a-zA-Z0-9._]){4,19}$':匹配长度为5-20的字符串,必须以字母开头并且可带字母、数字、“_”、“.”的字符串。
'^(\w){6,20}$':匹配长度为6-20的字符串,可以包含字母、数字、下划线。
'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$':检查给定字符串是否为合法IP地址。
r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$':检查给定字符串是否为手机号码。
'^[a-zA-Z]+$':检查给定字符串是否只包含英文字母大小写。
'^\w+@(\w+\.)+\w+$':检查给定字符串是否为合法电子邮件地址。
r'(\w)(?!.*\1)':查找字符串中每个字符的最后一次出现。
r'(\w)(?=.*\1)':查找字符串中所有重复出现的字符。


'^(\-)?\d+(\.\d{1,2})?$':检查给定字符串是否为最多带有2位小数的正数或负数。
'[\u4e00-\u9fa5]':匹配给定字符串中所有汉字。
'^\d{18}|\d{15}$':检查给定字符串是否为合法身份证格式。
'\d{4}-\d{1,2}-\d{1,2}':匹配指定格式的日期,例如2016-1-31。
'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[,._]).{8,}$':检查给定字符串是否为强密码,必须同时包含英语字母大写字母、英文小写字母、数字或特殊符号(如英文逗号、英文句号、下划线),并且长度必须至少8位。
"(?!.*[\'\"\/;=%?]).+":如果给定字符串中包含'、"、/、;、=、%、?则匹配失败。
'(.)\\1+':匹配任意字符的两次或多次重复出现。
'((?P<f>\b\w+\b)\s+(?P=f))':匹配连续出现两次的单词。
'((?P<f>.)(?P=f)(?P<g>.)(?P=g))':匹配AABB形式的成语或字母组合。


r"/d+(?=[a-z]+)":匹配连续的数字并且最后一个数字跟着小写字母。
r"/d+(?![a-z]+)":匹配连续的数字,并且最后一个数字后面不能跟小写字母。
r"(?<=[a-z])\d+":匹配连续的数字,并且第一个数字的前面是小写字母。
r"(?<![a-z])\d+":连续的数字,并且第一个数字的前面不能小写字母。
r'\d{3}(?!\d)':匹配三位数字,而且这三位数字的后面不能是数字。
r'\b((?!abc)\w)+\b':匹配不包含连续字符串abc的单词。
r'(?<![a-z])\d{7}':匹配前面不是小写字母的七位数字。
r"(?<=<(\w{4})>)(.*)(?=<\/\1>)":匹配"<span> hello world </span>"中的span和hello world。

2、re的几个函数

re.match(patter, str)
作用:从字符串的起始位置匹配模式串,也就是从开头匹配,如果不匹配就结束。

re.search(patter, str)
作用:完整扫描依次字符串,找到第一次出现符合的。

re.findall()
返回一个list,查到所有符合的字符串

re.finditer() 返回一个迭代器,和findall差不多

s2 = 'ABCdefabbcd8239'
print(re.match('[a-z]{1,3}', s2)) # None 因为开头第一个不匹配
print(re.search('[a-z]{1,3}', s2)) # <re.Match object; span=(3, 6), match='def'> 这是一个re.match对象
print(re.search('[a-z]{1,3}', s2).span()) # (3, 6)
print(re.search('[a-z]{1,3}', s2).group()) # def
print(re.findall('[A-Za-z0-9]', s2)) # 不会去重,比如b出现两次 ['A', 'B', 'C', 'd', 'e', 'f', 'a', 'b', 'b', 'c', 'd', '8', '2', '3', '9']
print(re.findall('[a-z]{1,3}', s2)) # ['def', 'abb', 'cd']
print(re.finditer('[a-z]{1,3}', s2)) # 这是一个迭代器,不能像列表一样输出
for i in re.finditer('[a-z]{1,3}', s2):
    print(i) # i 是一个re.match对象,i.group()可以输出字符串

当字符串中有分组的时候,会出现一定的不同


# 当存在分组时:search 和 match返回的不是单纯的字符串,是一个还有k个元素的元组(k和()的个数相关)
# 下面的模式串存在两个括号,进行匹配后,使用group(i)可以输出每个括号的内容
print(re.match(r"(\d+)@(\w+).com", s1)) # <re.Match object; span=(0, 16), match='12345678@163.com'>
print(re.match(r"(\d+)@(\w+).com", s1).group()) # 12345678@163.com
print(re.search(r"(\d+)@(\w+).com", s1).group()) # 12345678@163.com
print(re.search(r"(\d+)@(\w+).com", s1).group(0)) # 12345678@163.com
print(re.search(r"(\d+)@(\w+).com", s1).group(1)) # 12345678
print(re.search(r"(\d+)@(\w+).com", s1).group(2)) # 163
print(re.search(r"(\d+)@(\w+).com", s1).groups()) # ('12345678', '163')
print(re.search(r"((\d+)@(\w+).com)", s1).groups()) # ('12345678@163.com', '12345678', '163')

print("----------------")


#正则有两个分组,我们需要分别获取分区,分组从0开始,group方法不传递索引默认为0,代表了整个正则的匹配结果
for i in re.finditer(r"(\d+)@(\w+).com", s1) :
    print(i.groups()) # 三行分别输出('12345678', '163') ('2345678', '163') ('345678', '163')
    print(i.group()) # 三行分别输出 12345678@163.com 2345678@163.com 345678@163.com
    print(i.group(1)) #  三行分别输出 12345678 2345678 345678

print("-------------")
print(re.findall(r"(\d+)@(\w+).com", s1)) # 一个列表 [('12345678', '163'), ('2345678', '163'), ('345678', '163')]
for i in re.findall(r"(\d+)@(\w+).com", s1):
    print(i[0]) # 三行分别输出 12345678 2345678 345678
    print(i) # 三行分别输出 ('12345678', '163'), ('2345678', '163'), ('345678', '163')


print("-------------")

# findall 返回的是元组,而不是re.match对象,无法直接获得想要的字符串
# 解决方法为:加一个整体的括号
print(re.findall(r"((\d+)@(\w+).com)", s1)) # 一个列表 [('12345678@163.com', '12345678', '163'), ('2345678@163.com', '2345678', '163'), ('345678@163.com', '345678', '163')]
for i in re.findall(r"((\d+)@(\w+).com)", s1):
    print(i[0]) # 三行分别输出 12345678@163.com 2345678@163.com 345678@163.com

posted @ 2021-11-15 17:36  MJT12044  阅读(291)  评论(2编辑  收藏  举报