正则表达式的基础内容就不一一罗列了,都记录在了有道云笔记上
正则表达式重要点总结
1.断言
了解一个零宽的知识:占有字符和零宽度:
如果子表达式匹配到的是字符内容,而非位置,并被保存到最终的结果中,那么就认为这个字表达式是占有字符的;如果子表达式匹配的仅仅是位置,或者匹配的内容并不保存最终的匹配结果中,那么就认为这个表达式是零宽度的。
零宽断言 | 举例 |
---|---|
rained(?=exp) | 匹配右边右边一定紧挨着exp的rained |
(?<=exp)rained | 匹配左边一定挨着exp的rained |
负向零宽断言 | 举例 |
---|---|
rained(?!exp) | 匹配右边右边一定不紧挨着exp的rained |
(?<!exp)rained | 匹配左边一定不紧挨着exp的rained |
2.分组
分组 | 解释 |
---|---|
(exp) | 使用()指定一个字表达式,也叫分组,捕获后会自动分配组号从1开始,也可以改变优先级 |
(?:exp) | 不需要捕获分组,仅仅是为了改变优先级 |
(?P< name>exp) | Python中的命名分组 |
3.引擎选项
模式 | 说明 | Python使用方法 |
---|---|---|
IgnoreCase | 匹配时忽略大小写 | re.I、re.IGNORECASE |
Singleline | 单行模式,可以匹配所有字符,包括\n | re.S、re.DOTALL |
Multiline | 多行模式^行首、$行尾部 | re.M、re.MULTILINE |
IgnorePatternWhitespace | 忽略表达式中的空白字符,如果要使用空白字符用转义,#可以用来注释 | re.X、re.VERBOSE |
注解:
①默认模式下:不能匹配换行符,只是一行,只有一个开头和结尾
②单行模式下: .可以匹配换行符
③多行模式下: .不能匹配换行符,每行都有行首和行位
Python中re模块常用方法
python re模块官方文档点这里
1.re.compile(pattern,flags=0)
flags表示匹配的模式,可以通过位的OR操作来结合(|操作符)。
返回正则表达式对象regex,可以用于匹配,通过这个对象的方法match(),search()以及其他描述。
In [1]: import re
In [2]: s = "abc123"
In [3]: regex = re.compile("\d+")
In [4]: regex.search(s)
Out[4]: <re.Match object; span=(3, 6), match='123'>
In [5]: regex.search(s).group()
Out[5]: '123'
注解: 通过re.compile()编译后的样式,和模块级的函数会被缓存,所以少数的正则表达式使用无需考虑编译的问题。
2.单次匹配的方法==
1° re.match(pattern,string,flags=0)
只能在位置0匹配,无视多行模式的行首,位置0
单次匹配,匹配不到返回None
返回值为match对象
2° re.search(pattern,string,flag=0)
单次匹配,只返回第一个匹配到的,匹配不到返回None
找到就不往后面找了
返回值为match对象
3° re.fullmatch(pattern,string,flags=0)
全长匹配,应用于所有字符串,必须全部匹配上,否则返回None
返回值为match对象
3.全文匹配的方法
1° re.findall(pattern,string,flags=0),返回的东西!!!
全局匹配,返回所有满足pattern的string的一个列表
return a list
如果正则表达式带分组
-
一个分组:返回组列表list of groups =>> [‘a’, ‘b’,]
因为groups()是一个字符串的元组,所有返回为字符串的list -
多个分组:返回元组列表list of tuples => [(), (),]
因为groups()是多个字符串的元组,所以返回元组列表
In [1]: import re
In [2]: s ="band\nbag\nbad\nabsolute"
In [3]: re.findall("b[a-z]+(d)",s) # 返回一个字符列表
Out[3]: ['d', 'd']
In [4]: re.findall("b(?P<A>a)\w*(?P<B>d)",s) # 返回一个元组列表
Out[4]: [('a', 'd'), ('a', 'd')]
In [5]: re.findall("b[a-z]+d",s)
Out[5]: ['band', 'bad']
2° re.finditer(pattern,string,flags=0)
返回一个保存了match对象的iterador
从左到右依次匹配,匹配按熟悉怒排列。空匹配也包括在结果内。
In [1]: import re
In [2]: s = "a1b2c3d4"
In [3]: x = re.finditer("\d",s)
In [4]: for i in x:
...: print(i)
...:
<re.Match object; span=(1, 2), match='1'>
<re.Match object; span=(3, 4), match='2'>
<re.Match object; span=(5, 6), match='3'>
<re.Match object; span=(7, 8), match='4'>
3° 匹配替换
re.sub(pattern,repl,string,count,flags)
使用pattern对字符串string进行匹配,对匹配项使用repl替换
In [7]: re.sub("\d","☆",s)
Out[7]: 'a☆b☆c☆d☆'
In [8]: s = "a1b2c3d4"
In [9]: re.sub("\d","☆",s)
Out[9]: 'a☆b☆c☆d☆'
In [10]: s
Out[10]: 'a1b2c3d4'
re.subn(pattern, repl, string, count=0, flags=0)
行为和sub()相同,但是返回一个元组(字符串,替换次数)
In [10]: s
Out[10]: 'a1b2c3d4'
In [11]: re.subn("\d","☆",s)
Out[11]: ('a☆b☆c☆d☆', 4)
In [12]: s
Out[12]: 'a1b2c3d4'
注意上面两种匹配替换模式不对原字符串进行操作,返回值为替换过的副本。
4° 分隔字符串
re.split(pattern,string,maxsplit,flags)
返回值为一个列表。
下面举例易错点:
In [12]: s
Out[12]: 'a1b2c3d4'
In [13]: re.split("(\w)",s)
Out[13]: ['', 'a', '', '1', '', 'b', '', '2', '', 'c', '', '3', '', 'd', '', '4', '']
In [14]: re.split("\w",s)
Out[14]: ['', '', '', '', '', '', '', '', '']
In [15]: re.split("\d",s)
Out[15]: ['a', 'b', 'c', 'd', '']
In [16]: re.split("(\d)",s)
...:
Out[16]: ['a', '1', 'b', '2', 'c', '3', 'd', '4', '']
注意:
①如果pattern中捕获到括号(也就是分组),那么所有的组里的文字也会包含在返回的列表中。
②如果分隔符里有捕获组合,并且匹配到字符串的开始,那么结果将会以一个空字符串开始。对于结尾也一样。
4.分组
使用小括号的pattern分组捕获的数据被放到了group中。
对于返回为match对象的方法,总结以下几点:
- groups()和group()可以通过match对象获得
- group()和group(0)相同,
- group(n)如果n超界,会IndexError
- groups()是所有group组成的元组,group(0)除外
对于命名分组(?Pexp)可以使用groupdict返回所有命名的分组
可以使用matchobj.group(name)获取对应分组捕获的值
In [21]: s = "abc123_ "
In [22]: re.search("([a-z]+)",s)
Out[22]: <re.Match object; span=(0, 3), match='abc'>
In [23]: x = re.search("([a-z]+)",s)
In [24]: x.groups() # 返回所有分组匹配结果组成的元组
Out[24]: ('abc',)
In [25]: x.group() == x.group(0) # 这两个值相同, 返回pattern匹配的结果
Out[25]: True
In [26]: x.group(0)
Out[26]: 'abc'
In [27]: x.group(1) # 返回第一个分组匹配的结果
Out[27]: 'abc'
In [28]: x.group(2) # 分组索引超界,报错IndexError
Traceback (most recent call last):
File "<ipython-input-28-43f0dc0c9eec>", line 1, in <module>
x.group(2)
IndexError: no such group
经典正则表达式练习题
正则表达式结合python验证密码强度问题
题目要求:
判断密码强度(因为只包含\w内的不包括汉字的密码,也不健壮…)
实际环境:
大写字母,小写字母,数字,下划线等除了汉字和空白字符的字符
拿到一个pwd,反馈密码强度
三个强度:weak,middle,strong
规则:
1.只含有二种字符的就是weak
2.含有三种的字符的就是midum
3.含有四种的就是strong
import re
def jduge(pwd):
# 下面来判断密码强度
Number = re.compile("[0-9]")
Lower_case = re.compile("[a-z]")
Upper_case = re.compile("[A-Z]")
others = re.compile("[^a-zA-Z0-9]")
type = 0 # 特征值
# 判断是否是合法字符
if len(pwd) < 8 or len(pwd) > 15:
print("Insufficient length")
elif re.search("\W|[^\x00-\xff]",pwd):
print("invalid pwd")
elif re.match("_",pwd): #查看是否有中文出现
print("invalid pwd")
else:
if Number.search(pwd):
type += 1
if Lower_case.search(pwd):
type += 1
if Upper_case.search(pwd):
type += 1
if others.search(pwd):
type += 1
if type < 3:
print("weak pwd")
if type == 3:
print("midum pwd")
if type == 4:
print("strong pwd")
jduge("daMASD_1")
代码比较粗糙