第八章:正则表达式
正则表达式:精确匹配或者模糊匹配
比如:匹配所有日志中的ip,匹配所有的响应时间。
re:regular expression
所有的语言使用的正则大同小异
Match:表示从字符串开头匹配,如果从第一个字符就不能匹配,则表示匹配失败。
1、match()从开头匹配,一个结果的匹配
>>> import re
>>> re.match(r"l","labd")
<_sre.SRE_Match object; span=(0, 1), match='l'>
>>> type(re.match(r"l","labd"))
<class '_sre.SRE_Match'>
>>> re.match(r"l","abc")
>>> print(re.match(r"l","abc"))
None
>>>
⚠️没有找到返回之后无数据,但是print之后,输出的是none。
r”l”是正则表达式,“labd”是匹配的目标字符串
r的写与不写:
>>> re.match("l","labc")
<_sre.SRE_Match object; span=(0, 1), match='l'>
>>> print(re.match(r"\d","9abc"))
<_sre.SRE_Match object; span=(0, 1), match='9'>
>>> print(re.match("\\d","9abc"))
<_sre.SRE_Match object; span=(0, 1), match='9'>
>>> dir(re.match("\\d","9abc"))
['__class__', '__copy__', '__deepcopy__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'end', 'endpos', 'expand', 'group', 'groupdict', 'groups', 'lastgroup', 'lastindex', 'pos', 're', 'regs', 'span', 'start', 'string']
2、search任意匹配,一个结果的匹配
>>> re.search(r"\d","abcd1ed")
<_sre.SRE_Match object; span=(4, 5), match='1'>
任意匹配,只要匹配到一次就成功了。
3、group()打印所有正则表达所匹配的内容
>>> re.search(r"\d","abcd1ed").group()
'1'
>>> re.search(r"cd\ded","abcd1ed").group()
'cd1ed'
4、\d:匹配一个和多个数字
\d:匹配一个数字
\d:匹配多个数字
>>> re.search(r"\d","abc1")
<_sre.SRE_Match object; span=(3, 4), match='1'>
>>> re.search(r"\d+","abc12345")
<_sre.SRE_Match object; span=(3, 8), match='12345'>
5、findall(多个结果的匹配)将所有的正则表达式从头到尾遍历一遍,只要匹配到的都放在一个列表里
>>> re.findall(r"\d+","a1b2c3d4")
['1', '2', '3', '4']
6、\D:匹配非数字
>>> re.search(r"\D","a123ed").group()
'a'
>>> re.search(r"\D","1223a123ed").group()
'a'
>>> re.search(r"\D+","12bc12ed").group()
'bc'#匹配到一个结果就结束了
>>> re.findall(r"\D+","12bc12ed")
['bc', 'ed']#匹配到多个结果,匹配到的都在一个列表里
7、\w:匹配数字和字母包含大小写
>>> re.search(r"\w","12Ab3c").group()
'1'
>>> re.findall(r"\w+","12Ab3c")
['12Ab3c']
>>> re.search(r"\w+","12Ab3c").group()
'12Ab3c'
常见的错误:
>>> re.match(r"\w"," abc")
>>> print(re.match(r"\w"," abc"))
None
>>> print(re.match(r"\w"," abc").group())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'
>>>
8、\W:匹配非数字且字母
>>> re.search(r"\W+","12#\@\%Ab3c").group()
'#\\@\\%'
>>> re.findall(r"\W+","12#\@\%Ab3c")
['#\\@\\%']
9、\s:匹配空白(空格、\t、\r、、)
>>> re.search(r"a\s+a","113a a#").group()
'a a'
>>> re.findall(r"a\s+a","12a a*")
['a a']
>>> re.search(r"\s","\t113aa#").group()
'\t'
10、\S:匹配非空白
>>> re.search(r"\S+","113a a#").group()
'113a'
>>> re.findall(r"\S+","113a a#")
['113a', 'a#']
\d、\w、\s表示匹配的内容,“+”表示匹配的个数,一个或者多个
11、*:表示匹配0个或者多个
正则表达式的贪婪性:尽量多匹配
>>> re.match(r"\w*","abc").group()
'abc'
>>> re.match(r"\w*","a1b2c3").group()
'a1b2c3'
>>> re.findall(r"\d*","a1b2c3")
['', '1', '', '2', '', '3', '']
>>> re.match(r"\w*"," a1b2c3").group()
''
>>> re.findall(r"\W*","a *b \t ")
['', ' *', '', ' \t ', '']
>>> re.findall(r"\W+","a *b \t ")
[' *', ' \t ']
12、加“?”限制贪婪者:
>>> re.match(r"\w*"," abc").group()
''
>>> re.match(r"\w*","abc").group()
'abc'
>>> re.match(r"\w+","abc").group()
'abc'
>>> re.match(r"\w+?","abc").group()
'a'
>>> re.match(r"\w*?","abc").group()
''
⚠️:“*?”表示匹配为空字符串,一般正则在限制贪婪性的时候,不会在这样写。
13、{a,b}:表示匹配a个到b个贪婪性
正则表达式的贪婪性,尽量多匹配
多加问号:表示抑制正则表达式的贪婪性
>>> re.search(r"a","aaabaaa")
<_sre.SRE_Match object; span=(0, 1), match='a'>
>>> re.search(r"a{3}","aaabaaa")
<_sre.SRE_Match object; span=(0, 3), match='aaa'>
>>> re.search(r"a{1,3}","aaabaaa").group()
'aaa'
>>> re.search(r"a{1,3}?","aaabaaa").group()
'a'
>>> re.search(r"a{1,3}","a").group()
'a'
>>> re.search(r"a{1,3}","aa").group()
'aa'
>>> re.search(r"a{1,3}","aaa").group()
'aaa'
>>> re.search(r"a{1,3}","aaaa").group()
'aaa'
>>> re.search(r"a{1,3}?","aaaa").group()
'a'
例题中的匹配1-3次都是可以的。
>>> s="abc13 33"
>>> if re.search(r"\d",s):
... print("字符串有数字")
... else:
... print("字符串没有数字")
...
字符串有数字
>>> s="abc13 33"
>>> if re.findall(r"\d",s):
... print("字符串有数字")
... else:
... print("字符串没有数字")
...
字符串有数字
>>>
练习题:判断一个字符串是否有连续的5个数字。
>>> s="abc 13 123"
>>> if re.findall(r"\d{5}",s):
... print("字符串中有连续的5个数字")
... else:
... print("字符串中没有连续的5个数字")
...
字符串中没有连续的5个数字
>>> s="abc 13123"
>>> if re.findall(r"\d{5}",s):
... print("字符串中有连续的5个数字")
... else:
... print("字符串中没有连续的5个数字")
...
字符串中有连续的5个数字
14、匹配的范围[a-z][A-Z][4-8]{5}
>>> s="1 I am a good man"
>>> if re.search(r"[a-zA-z]{5}",s):
... print("got it")
...
>>> s="aa 45678"
>>> if re.search(r"[4-8]{5}",s):
... print("got it")
...
got it
>>>
>>> re.search(r"[a-c|D-f]+","a12bc1D245FE").group()
'a'
>>> re.findall(r"[a-c|D-f]+","a12bc1D245FE")
['a', 'bc', 'D', 'FE']
>>> re.search(r"[a-c|D-F]+","acDF").group()
'acDF'
>>> re.search(r"[a-zA-Z0-9]+","A1AB2cDeF4").group()
'A1AB2cDeF4'
>>> re.findall(r"[a-zA-Z0-9]+","A1AB2cDeF4")
['A1AB2cDeF4']
>>> re.search(r"[abcd]+","abcd").group()
'abcd'
>>> re.search(r"ab|cd","abc").group()
'ab'
>>> re.findall(r"ab|cd","abcdef")
['ab', 'cd']
[ab]表示匹配其中之一都可以
{1,3}表示匹配从几个到几个,只是指定数量
15、?:表示匹配0次或者1次
>>> s="1abcd"
>>> re.match(r"1?",s).group()
'1'
>>> re.match(r"1?","abc").group()
''
“?”与“”的区别:“?”最多只能匹配一个,“”可以匹配多个
>>> re.match(r"\d?","1233abc").group()
'1'
>>> re.match(r"\d*","1233abc").group()
'1233'
16、分组:有几个括号就有几个分组
>>> re.search(r"a(\d+)c","a1234c")
<_sre.SRE_Match object; span=(0, 6), match='a1234c'>
>>> re.search(r"a(\d+)c","a1234c").group()
'a1234c'
>>> re.search(r"a(\d+)c","a1234c").group(1)
'1234'
>>> re.search(r"(a)(\d+)(c)","a1234c").group(1)
'a'
>>> re.search(r"(a)(\d+)(c)","a1234c").group(2)
'1234'
>>> re.search(r"(a)(\d+)(c)","a1234c").group(3)
'c'
>>>
17、正则工作原理:
正则的扫描顺序:从第一个字符开始向后扫描
>>> re.match(r"1","1b")匹配对象,匹配到后,就不在向后匹配了
>>> re.match(r"1","0b")None第一个就没匹配上,就不在向后匹配了
>>> re.search(r"1","ab1b")匹配对象,就不再向后匹配了
>>> re.search(r"1","abb")None,把所有的字符串内容扫描一遍
>>> re.search(r"\d+","ab113d")匹配对象113,就不再向后匹配了
>>> re.match(r"1","1b")
<_sre.SRE_Match object; span=(0, 1), match='1'>
>>> re.match(r"1","0b")
>>> print(re.match(r"1","0b"))
None
>>> re.search(r"1","ab1b")
<_sre.SRE_Match object; span=(2, 3), match='1'>
>>> re.search(r"1","abb")
>>> print(re.search(r"1","abb"))
None
>>> re.search(r"\d+","ab113d")
<_sre.SRE_Match object; span=(2, 5), match='113'>
>>>
18、re.I忽略大小写
>>> re.match(r"a","abc")
<_sre.SRE_Match object; span=(0, 1), match='a'>
>>> re.match(r"a","Abc",re.I)
<_sre.SRE_Match object; span=(0, 1), match='A'>
>>> re.match(r"a","Abc")
>>> print(re.match(r"a","Abc"))
None
19、“.”表示匹配所有的字符,除了回车(\n)
>>> re.search(r".","abcd").group()
'a'
>>> re.search(r".","2abcd").group()
'2'
>>> re.match(r".","\nbcd").group()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'
>>> re.match(r"\.",".d").group()
'.'
>>> re.match(r"\\","\\").group()
'\\'
>>> print("\\")
\
>>> re.match("\\\\","\\").group()
'\\'