#正则表达式由一些 [普通字符] 和一些 [元字符] 组成:
(1)普通字符包括大小写字母和数字
(2)元字符具有特殊含义,大体种类分为如下:
1.预定义字符集,字符组
2.量词
3.边界符
4.分组
匹配内容 | |
---|---|
. | 匹配任意字符,除了换行符\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.正常分组()
# (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']