Day22 正则表达式

1.正则表达式所包含的元素种类

#正则表达式由一些 [普通字符] 和一些 [元字符] 组成:
(1)普通字符包括大小写字母和数字
(2)元字符具有特殊含义,大体种类分为如下:
1.预定义字符集,字符组
2.量词
3.边界符
4.分组

1.1匹配单个字符 => [元字符] 预定义字符集

预定义字符集 匹配内容
. 匹配任意字符,除了换行符\n
\d 匹配数字
\D 匹配非数字
\w 匹配字母或数字或下划线 (正则函数中,支持中文的匹配)
\W 匹配非字母或数字或下划线
\s 匹配任意的空白符
\S 匹配任意非空白符
\n 匹配一个换行符
\t 匹配一个制表符
[] 匹配中括号内列举的字符

 1.2匹配多个字符 => [元字符] 量词符号

匹配单个字符:

\d 匹配数字
\D 匹配非数字
"""
lst = re.findall("\d","sadfsdfsa 98&*^&^&92sdf3sdf839 sdf_as 神秘男孩 89")
print(lst)
lst = re.findall("\D","sadfsdfsa 98&*^&^&92sdf3sdf839 sdf_as 神秘卫星 89")
print(lst)
# ['9', '8', '9', '2', '3', '8', '3', '9', '8', '9']
# ['s', 'a', 'd', 'f', 's', 'd', 'f', 's', 'a', ' ', '&', '*', '^', '&', '^', '&', 's', 'd', 'f', 's', 'd', 'f', ' ', 's', 'd', 'f', '_', 'a', 's', ' ', '神', '秘', '卫', '星', ' ']
"""
\w 字母数字下划线 包含中文(正则函数当中支持中文的匹配)
\W 匹配非字母或者数字或者下划线或者中文
"""
lst = re.findall("\w","09090sdf909sdf_+()()&*&*%^%^你好sd")
print(lst)
lst = re.findall("\W","09090sdf909sdf_+()()&*&*%^%^你好sd")
print(lst)
# ['0', '9', '0', '9', '0', 's', 'd', 'f', '9', '0', '9', 's', 'd', 'f', '_', '你', '好', 's', 'd']
# ['+', '(', ')', '(', ')', '&', '*', '&', '*', '%', '^', '%', '^']

"""
\s 匹配到任意的空白字符
\S 匹配到任意非空白字符
"""

strvar = """
"""
lst = re.findall("\s","         ")
print(lst)
lst = re.findall("\s",strvar)
print(lst)
lst = re.findall("\S","      dkladdk dsad dsajlk")
print(lst)
# [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
# ['\n']
# ['d', 'k', 'l', 'a', 'd', 'd', 'k', 'd', 's', 'a', 'd', 'd', 's', 'a', 'j', 'l', 'k']

"""
\n 匹配换行
\t 匹配一个制表符
"""
strvar = """
今天 拉                 肚   子 
"""
lst = re.findall(r"\n",strvar)
print(lst)
# ['\n', '\n']
lst = re.findall(r"\t",strvar)
print(lst)
#### 字符组练习 必须从字符组选一个,如果一个都没有则匹配不成功
lst = re.findall("[123]","s3dafs2s1")
print(lst)
# ['3', '2', '1']
print(re.findall('a[abc]b','aab abb acb adb'))
# ['aab', 'abb', 'acb']

 匹配多个字符:

###(二) 匹配多个字符 => [元字符] 量词符号
# (1) 重复0个或者1个a
print(re.findall('a?b','abbzab abb aab')) 
# ['ab', 'b', 'ab', 'ab', 'b', 'ab']
# (2) + 重复1个或者多个a
print(re.findall('a+b','b ab aaaaaab abb'))
# ['ab', 'aaaaaab', 'ab']
# (3) * 重复0个或者多个a

print(re.findall('a*b','b ab aaaaaab abbbbbbb'))
# ['b', 'ab', 'aaaaaab', 'ab', 'b', 'b', 'b', 'b', 'b', 'b']
# (4)(m,n) 重复m个至n个(重复的是量词符号前面的那字符)
print(re.findall('a{1,3}b','aaab ab aab abbb aaz aabb aaaaaaaaaabb'))
# 至少重复a一次
# ['aaab', 'ab', 'aab', 'ab', 'aab', 'aaab']
print(re.findall('a{1}b','aaab ab aab abbb aaz aabb aaaaaaaaaabb'))
# 只重复一次
# ['ab', 'ab', 'ab', 'ab', 'ab', 'ab']
print(re.findall('a{1,}b','aaab ab aab abbb aaz aabb aaaaaaaaaabb'))
# 重复a 1次或者是多次
# ['aaab', 'ab', 'aab', 'ab', 'aab', 'aaaaaaaaaab']

 1.3匹配多个字符 => [元字符] 量词符号

# 贪婪匹配与非贪婪匹配 [语法:两次的后面加上?号]
"""
贪婪匹配: 默认向更多次数匹配 底层用的是扩回溯算法
非贪婪匹配: 默认向更少的次数匹配



在量词的后面加上一个?号,就是非贪婪匹配 例如: .*? .?? .+? .{m,n}?
其中用的最多的是.*?如果遇到了子这个字,在贪婪模式下,匹配到第一个就返回
 回溯算法:
 向左向右就行匹配, 一直向后找,知道再也找不到了 回到,拿里右侧那个值
"""

 贪婪匹配

strvar = "刘能和刘铁锤和刘大棍子12313子"
# (1)
lst = re.findall("刘.",strvar)
# 贪婪模式
print(lst)
# 其中刘的意思是以刘子开头,其次就是.的意思就是后面随便一个字符都行,匹配出三个
# ['刘能', '刘铁', '刘大']
# (2)
lst = re.findall("刘.?", strvar)
# 刘的意思是以刘字开头,然后刘子后面跟一个除了\n的字符串,然后?是要么重复.0次要么重复.1次
print(lst)
# ['刘能', '刘铁', '刘大']
lst = re.findall("刘.*", strvar)
print(lst)
# 刘的话就是以刘子开头,然后,后面跟着一个除了\n的字符串,*就是重复.0次或者多次.
# 匹配是贪婪的故是重复很多的.
# ['刘能和刘铁锤和刘大棍子12313子']
lst = re.findall("刘.{1,20}子", strvar)
print(lst)
# 匹配出的字符必须是刘开始,然后可以重复.的次数是最多20次,但是最后匹配出的字符的结尾是以子结尾的
# 由于是贪婪的匹配到第一个子的时候,正则不会停止匹配直到第二个子,如果满足20个字符才会把字符串给输出来
# 故结果是:
# ['刘能和刘铁锤和刘大棍子12313子']
# 贪婪匹配
# (1)
lst = re.findall(r".*d\b", "word pwd abc")
print(lst)
# ['word pwd']
# 正则式子要求可以是0个字符或者是多个字符并且以d为右边的字符,由于没有?
# 由于正则表达式的特性他是贪婪的,那么公式会一直匹配所给的字符串中,直到匹配到字符串中右边没有以d为边界位置的位置 
# 贪婪模式的结果特性是匹配出来的结果只有一个,就是贪婪把边界是d的字符串一次性读出来了
# 非贪婪匹配
# (2)
lst = re.findall(r".*?d\b", "word pwd abc")
print(lst)
# 这个和(1)的区别就是(1)是贪婪的,其次就是(2)是不贪婪的,
# 不贪婪的特性就是,可能让匹配的字符串可能会匹配出多个字符串,也就是多个结果满足条件
# 由于.*?前面没有限制是什么东西开头的,并且其中.的意思就是可以是任意字符开头包括空格,所以第二个被匹配出来的字符串是以空格开头的。
# .的意思就是,除了\n不行,其余的字符都能匹配
# ['word', ' pwd'] 

# (3) 优化版:舍掉空格
# 这个优化版相对于第二个的区别就是在.*?前面加了一个限制,防止空格的进入
# \S的意思就是匹配任意非空格的字符
lst = re.findall(r"\S*?d\b", "word pwd abc")
print(lst)
# ['word', 'pwd']
# 匹配的结果中就没有空格了
# 加了一个匹配开头的限制之后匹配出的结果如下
# 匹配单词的左边界
lst = re.findall(r"\bw.* ", "word abc")
print(lst)
#['word ']
# 正则式子的意思是匹配左边界为w的字符串,并且w后面的字符可以是0个或者是多个,并且还要是以空格结尾的字符
print(re.findall(r"\bw.* ", "word abc "))
#贪婪的结果
# ['word abc ']

  

非贪婪匹配:

# 非贪婪匹配
strvar = "刘能和刘铁锤和刘大棍子12313子"
lst = re.findall("刘.??", strvar)
# 正则匹配出的字符串是以刘开头的字符,然后就是重复.0次或者是多次,有后面有一个?那么正则表达式的匹配模式
# 是非贪婪的,那么选择重复0次也就是不要. 于是结果就是刘 刘 刘 了
print(lst)
# ['刘', '刘', '刘']
lst = re.findall("刘.+?", strvar)
# 正则匹配出的字符串是以刘字开头的字符,然后+是重复.1个或者多个,那么由于上面的表达式是非贪婪匹配那么选择重复.1次或者是多次,由于有后面有一个?那么正则表达式的匹配模式
# 是非贪婪模式,选择重复一次.就可以了
print(lst)
# ['刘能', '刘铁', '刘大']
lst = re.findall("刘.*?", strvar)
print(lst)
# 由于正则匹配的模式是非贪婪模式,又由于*的意思是重复前面的字符.0次或者是多次,
# 非贪婪选择0次就可以了,即.就消失了
# ['刘', '刘', '刘']
lst = re.findall("刘.*?子", strvar)
print(lst)
# 由于*是非贪婪模式,那么刘字后面选择不要.(字符),然后字符串是以字结尾的字符都满足条件
# 也就是说匹配到第一个子之后就结束匹配了。
# ['刘能和刘铁锤和刘大棍子']
lst = re.findall("刘.{1,20}?子", strvar)
# 贪婪和非贪婪是根据是否可以匹配得到来讲的,非贪婪就是在匹配得到的极限位置,一个一个返回,贪婪就是所有能匹配得到的最终返回
# 非贪婪的,那么选择在(1,20个字符中(也就是刘后面的字符))匹配到就可以,但是第二个是子
print(lst)

 1.4 匹配开头结尾 => [元字符] 边界符号

'''
^ 必须以某个字符开头,后面的字符无所谓
$ 必须以某个字符结尾,前面的字符无所谓
如果正则里面包含了^或者$ 意味要把字符串看成一个整体
# 把字符串看成一个整体,只要一个结果

# 1
print(re.findall("^g.*e",'giveme 1gfive gay'))
#  g的意思就是匹配字符中的格式是以g开头,然后g后面是一个点。
#  .的意思就是后面是1个字符,再后面是一个*
#  *的意思就是可以是0个.或者是多个多个.
#  e的意思就是匹配到的字符结尾是e
#  由于正则表达式是贪婪的所以,在不在量词*后面加上?的时候,它会匹配更多的以e结束的字符,直到没有e结尾的字符为止
#  故结果为;['giveme 1gfive']
# 2
print(re.findall('giveme' , 'giveme giveme'))
# 按照'giveme'就行匹配就可以了。
# ['giveme', 'giveme']

print(re.findall('^giveme$', 'giveme giveme'))
# ^ 这个的意思是必须是g开头,然后是e结尾
print(re.findall('^giv.me$' , 'giveme'))
# 这个的意思是以g开头e结尾
# .所在的位置为1个字符串,那么我们可以在后边需要匹配的字符串中找到e故能匹配
# ['giveme']
print(re.findall('^giveme$' , 'givemeq'))
# []
print(re.findall('^giveme$' , 'giveme'))
# ['giveme']
print(re.findall('five$' , 'aassfive00'))
# 匹配以e结尾的字符,没有
# []
print(re.findall('five$' , 'aassfive'))
# ['five']
print(re.findall('^g.*? ' , 'giveme 1gfive gay '))
# ^的意思就是以g开头
# .的意思是g后面跟一个字符,
# *的意思是修饰.的,是说要么0个要么多个.,
# ?的意思是非贪婪,那么匹配到第一个就完成了,由于.*?后面是一个空格,那么匹配到字符串中以g开头然后后面是一个空格就结束了
# ['giveme ']
strvar = "大哥大嫂大爷"
print(re.findall('', strvar))
# ['大', '大', '大']
print(re.findall('^大', strvar))
print(re.findall('大.$', strvar))
# ['大爷']
print(re.findall('^大.$',strvar))
# 正则字符算式要求以大字开头后面一个字结尾的字符串,但是看到^的时候我们发现我们只能把字符串看成一个整体,那么没有以大字开头,后面是一个字的字符串故不成立
# []
print(re.findall('^大.*?$',strvar))
# 公式的要求是以大字开头,然后后面有0个字符.但是加了*的话说明可以是一个.或者是多个..
# 但是后面还加?说明只有只要找到以大字开头,然后以大后边的字结尾即可,即是下面的结果。
# ['大哥大嫂大爷']
print(re.findall('^大.*?大$',strvar))
# 正则要求以大字开头,并且大字后面可以跟0个字符或者多个字符且还是以大结尾的字符串,
# 首先看结尾必须是大字结尾单凭这一点就可以把他干掉了
# []
print(re.findall('^大.*?爷$',strvar))
# 正则表达式要求以大字开头,然后可以是0个或者多个字符(但是不贪婪找到为目的),
# 其中需要找的字符的规则看.*?后面的要求它要求的是以爷子结尾,根据整个算式我们可以
# 知道表达式刚好满足
# ['大哥大嫂大爷']
### (3)匹配开头结尾 => [元字符]边界符号
"""
\b 用来匹配边界 word 匹配d为右边界 d\b匹配w为左边界 \bw
\b 退格 backspace 是一个转义字符
一般写正则表达式的时候,字符串的前面加上一个r,让转义符失效
"""

1.5匹配分组 => [元字符] 分组符号

# 1.正常分组()
# (1) 正产的情况下()圆括号就行分组可以用\1返回引用第一个圆括号匹配的内容
# (2) (?:正则表达式) 表示取消优先显示的功能
(正则表达式) 代表分组 findall 把所有分组的内容显示到列表里
(?:正则表达式) 代表分组findall 把所有的分组内容不显示到列表中

print(re.findall('.*?_good','wusir_good alex_good 神秘男孩_good'))
# ['wusir_good', ' alex_good', ' 神秘男孩_good']
print(re.findall('(.*?)_good', 'wusir_good alex_good神秘男孩_good'))
# ['wusir', ' alex', '神秘男孩']
print(re.findall('(?:.*?)_good', 'wusir_good, alex_good 神秘男孩_good'))
# 不显示括号里面的内容
# ['wusir_good', ', alex_good', ' 神秘男孩_good']

# | 代表或的意思
# 既想要匹配搭配abc 还要匹配到abcd
lst = re.findall("abc|abcd","abc234abcd234")
print(lst)
# ['abc', 'abc']
# 有缺陷 不能都匹配到
# 注意必须把字符串长的写在前面,字符串短的写在后面
# 改造一下
lst = re.findall("abcd|abc","abc234abcd234")
print(lst)
# ['abc', 'abcd']

# 匹配小数
'''
用\让原本有意义的字符变得无意义
.代表任意字符(除了\n)
如果想要让正则匹配到一个
用\.让点的意思失效
'''

# 3.14 34. .2342 234. . 2344.234
lst = re.findall("\d+\.\d+", "3.14 34. .2342 234. . 2344.234")
print(lst)
# ['3.14', '2344.234']
# 匹配到小数和整数
lst = re.findall("\d+\.\d+|\d+","3.14 34. .2342 234. . 2344.234")
print(lst)
# ['3.14', '34', '2342', '234', '2344.234']

# 使用分组的形式来匹配小数和整数
lst = re.findall("\d+(?:\.\d+)?","3.14 34. .2342 234. . 2344.234")
print(lst)
# ['3.14', '34', '2342', '234', '2344.234']
# 匹配到135和17的手机号
lst = re.findall("135|^171\d{8}", "171sdadadf 123241711132421321")
print(lst)
# []
lst = re.findall("135|171[0-9]{8}", "171sadasjd 17165439875")
print(lst)
# ['17165439875']

### search 通过正则匹配出第一个对象返回,通过group取出对象中的值
"""
findall 把满足条件的所有值都找出来放到列表里面返回
search 找到一个满足条件的值就直接返回,扔到一个对象当中
想要获取对象中的值,用group 对象.group()
"""
obj = re.search("\d+","jsjdkajdlsaflaskfjsadsad90a8fafa798")
print(obj)
# <_sre.SRE_Match object; span=(24, 26), match='90'>
res = obj.group()
print(res)
# 90
# 匹配www.baidu.com 或者www.old.com
obj = re.search("(www)\.(baidu|oldboy)\.(com)","www.baidu.com www.oldboy.com")
res = obj.group()
print(res)
# 使用search匹配的时候只能匹配出一个
# www.baidu.com
# 数字1 代表拿第一个小括号里面的内容
res = obj.group(1)
print(res)
# www
res = obj.group(2)
print(res)
# baidu
res = obj.group(3)
print(res)
# com
# groups 一次性把所有小括号里面的内容匹配出来
res = obj.groups()
print(res)
# ('www', 'baidu', 'com')

# "5*6-7/3" 匹配5*6 或者 7/3
strvar = "5*6-7/3"
obj = re.search("\d+[*/]\d", strvar)
res = obj.group()
print(res)
# 5*6
lst = re.findall("\d+[*/]\d",strvar)
print(lst)
# ['5*6', '7/3']

猜你喜欢

转载自www.cnblogs.com/longerandergou/p/10920496.html