[Python进阶]Python正则表达式
文章目录
一、元字符
.
匹配除换行符之外的任何字符,当re.DOTALL
标记被指定时,则可以匹配包括换行符的任意字符。^
匹配字符串的开头$
匹配字符串的末尾或字符串末尾的换行符之前re*
重复匹配前面的字符零次或者更多次(贪婪模式:尽可能多的匹配遇到的重复)re+
重复匹配前面的字符1次或者更多次(贪婪模式)re?
重复匹配前面的字符0次或者1次(非贪婪模式)re{m}
重复匹配m次,例如,"o{2}“不能匹配"Bob"中的"o”,但是能匹配"food"中的两个o。re{n, }
精确匹配n个前面表达式。例如,"o{2,}“不能匹配"Bob"中的"o”,但能匹配"foooood"中的所有o。"o{1,}“等价于"o+”。“o{0,}“则等价于"o*”。re{m,n}
重复匹配m次或者n次(贪婪模式)re{m,n}?
{m,n}的非贪婪模式.\\
转义特殊字符或表示特殊序列[...]
表示一组字符,如果以”^"为第一个字符,表示一组字符的互补集.|
A|B, 选择分支,或者匹配A或者匹配B.
二、分组
(...)
(正则表达式分组):就是用一对圆括号“()”括起来的正则表达式。使用group(num)和groups()函数提取分组内容。group(0)提取整个正则表达式内容。(?P<name>...)
(命名分组):就是给具有默认分组编号的组另外再给一个别名。(?P=name)
或\数字
(后向引用):①以前面的以name为名称的组匹配的文本为分组内容,匹配后面的内容②,\n表示引用第n个组。而\0则引用整个被匹配的正则表达式本身。后向引用用于匹配一些重复的字符串。(?=pattern)
(前向肯定断言):当该表达式匹配成功的时候,它的前面的表达式才会匹配.(?<=pattern)
(后向肯定断言):匹配以pattern开始的后面部分的字串,pattern只能是一个明确的表达式.(?!pattern)
(前向否定断言):当该表达式不匹配的时候,它的前面的表达式都会匹配成功(?<!pattern)
(后向否定断言):匹配不是以pattern开始的后面部分的字串.只能是固定的长度
>>>print(re.match('(?P<first_name>\w+) (?P<last_name>\w+)','Eric Brown').group())
Eric Brown
#通过命名分组进行后向引用
>>> re.search(r'(?P<name>go)\s+(?P=name)\s+(?P=name)', 'go go go').group('name')
'go'
#通过默认分组编号进行后向引用
>>> re.search(r'(go)\s+\1\s+\1', 'go go go').group()
'go go go'
#交换字符串的位置
>>> s = 'abc.xyz'
>>> re.sub(r'(.*)\.(.*)', r'\2.\1', s)
'xyz.abc'
#如果在匹配的过程中,需要同时用到前向肯定断言和后向肯定断言,那么必须将后向肯定断言写在正则语句的前面,前向肯定断言写在正则语句的后面,表示后向肯定模式之后,前行肯定模式之前。
>>> s1='''char *a="hello world"; char b='c'; /* this is comment */ int c=1; /* this is multiline comment */'''
>>> re.findall( r'(?<=/\*).+?(?=\*/)' , s1 ,re.M|re.S)
[' this is comment ', ' this is multiline comment ']
#肯定断言
>>> print(re.match('(?<=abc)def', 'abcdef'))
None
>>> print(re.search('(?<=abc)def', 'abcdef'))
<_sre.SRE_Match object; span=(3, 6), match='def'>
>>> print(re.match('(\w+)(?<=zhang)san', 'myzhangsan').group())
myzhangsan
#否定断言
三、特殊字符序列
\number
:\A
:匹配字符串开始。\Z
:匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。\b
:匹配一个单词边界。\b
可以匹配的边界包括单词和特殊字符边界,比如$,#…
等。\B
:匹配非单词边界\d
:匹配任意数字,等价于 [0-9]。\D
:匹配任意非数字\s
:匹配任意空白字符,等价于 [\t\n\r\f]。\S
: 匹配任意非空字符\w
:匹配数字字母下划线\W
:匹配非数字字母下划线
四、正则表达式常用方法(函数)
compile
compile 函数用于编译正则表达式,返回编译后的正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。re.compile(pattern[, flags])
pattern
: 一个字符串形式的正则表达式flags
可选,表示匹配模式,具体参数为:re.I(re.IGNORECASE)
: 忽略大小写re.M(MULTILINE)
: 多行模式,使"^"和“$”能在一个换行符后继续使用。re.S(DOTALL)
: 点任意匹配模式,使"."能够匹配包括换行符的所有字符.re.L(LOCALE)
: 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定re.U(UNICODE)
: 仅供兼容性。忽略字符串模式(默认),并且禁止字节模式。re.X(VERBOSE)
: 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释
>>> p=re.compile('\d{4}\-\d{7}',re.A)
>>> print(type(p))
<class 're.Pattern'>
match
从头开始匹配一个正则表达式模式,如果匹配,则返回一个match对象,如果不匹配,则返回None,即使在多行模式下,匹配也是从整个字符串的开头开始,而不是从每行的开头开始。match(pattern, string, flags=0)
group()
可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。groups()
返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
# ip地址的匹配:正则(([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])\.){3}([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])
#1.直接由re调用match进行匹配
>>> m=re.match(r'(([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])\.){3}([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])','192.168.1.1')
>>> print(type(m))
<class 're.Match'>
>>> print(m.group())
192.168.1.1
#2.利用pattern对象进行匹配
>>> p=re.compile(r'(\d{1,3}\.){3}(\d{1,3})')
>>> m=p.match('192.168.1.1')
>>> print(type(m))
<class 're.Match'>
>>> print(m.group())
192.168.1.1
#正则匹配部分字符串,但不是整个字符串
>>> m=p.match('192.168.1.1 is my ip address')
>>> print(m)
<re.Match object; span=(0, 11), match='192.168.1.1'>
fullmatch
完全匹配,如果整个字符串匹配正则表达式,才会返回match对象,如果不匹配或有部分匹配,返回None.fullmatch(pattern, string, flags=0)
search
在字符串中搜索是否存在模式,不是从字符串的开头进行匹配,而是在整个字符串的所有位置进行查找,返回第一个符合条件的字符的match对象,并不会判断一个字符串有几个匹配。search(pattern, string, flags=0)
sub
替换字符串中出现的符合表达式的字符串,如果替换成功,则返回替换后的字符串,如果没有替换成功,则返回原字符串。re.sub(pattern, repl, string, count=0, flags=0)
repl
:要替换的字符串,可以是一个字符串,也可以是一个函数(方法),字符串中也可以含有正则。count
: 模式匹配后替换的最大次数,默认0表示替换所有的匹配。
>>> phone = "2004-959-559 # 这是一个电话号码"
>>> num = re.sub(r'#.*$', "", phone) # 删除注释
>>> print (num)
2004-959-559
>>> num = re.sub(r'\D', "", phone)# 移除非数字的内容
>>> print (num)
2004959559
#改变日期的格式
>>> s = '2017-11-27'
>>> import re
>>> print(re.sub('(\d{4})-(\d{2})-(\d{2})',r'\2/\3/\1', s))
11/27/2017
# repl 参数是一个函数
def double(matched):#将匹配的数字乘于 2
value = int(matched.group('value'))
return str(value * 2)
s = 'A23G4HFD567'
print(re.sub('(?P<value>\d+)', double, s))
#A46G8HFD1134
subn
subn
返回的是一个tuple,在该tuple中,有两个值,前面是返回的替换后的字符串,后面是替换的次数。
split
利用与表达式匹配的子字符串分割给定字符串, 返回的值是一个分割后的列表。split(pattern, string, maxsplit=0, flags=0)
>>> re.split('\W+', 'runoob, runoob, runoob.')
['runoob', 'runoob', 'runoob', '']
>>> re.split('(\W+)', ' runoob, runoob, runoob.')
['', ' ', 'runoob', ', ', 'runoob', ', ', 'runoob', '.', '']
>>> re.split('\W+', ' runoob, runoob, runoob.', 1)
['', 'runoob, runoob, runoob.']
>>> re.split('a*', 'hello world') # 对于一个找不到匹配的字符串而言,split 不会对其作出分割
['hello world']
findall
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。match
和 search
是匹配一次 findall
匹配所有。re.findall(string[, pos[, endpos]])
>>> import re
>>> s = "adfad asdfasdf asdfas asdfawef asd adsfas "
>>> reObj1 = re.compile('((\w+)\s+\w+)')①
>>> reObj1.findall(s)
[('adfad asdfasdf', 'adfad'), ('asdfas asdfawef', 'asdfas'), ('asd adsfas', 'asd')]
>>> reObj2 = re.compile('(\w+)\s+\w+')②
>>> reObj2.findall(s)
['adfad', 'asdfas', 'asd']
>>> reObj3 = re.compile('\w+\s+\w+')③
>>> reObj3.findall(s)
['adfad asdfasdf', 'asdfas asdfawef', 'asd adsfas']
①.当给出的正则表达式中带有多个括号时,列表的元素为多个字符串组成的tuple,tuple中字符串个数与括号对数相同,字符串内容与每个括号内的正则表达式相对应,并且排放顺序是按括号出现的顺序。
②.当给出的正则表达式中带有一个括号时,列表的元素为字符串,此字符串的内容与括号中的正则表达式相对应(不是整个正则表达式的匹配内容)。
③3.当给出的正则表达式中不带括号时,列表的元素为字符串,此字符串为整个正则表达式匹配的内容。
finditer
和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个match迭代器返回。
finditer(pattern, string, flags=0)
it = re.finditer(r"\d+","12a32bc43jf3")
for match in it:
print (match.group() ) #12 32 43 3
escape
转义字符串中所有的非数字字母字符。当要匹配的字符串含有正则表达式的元字符的时候,可以先利该方法进行转义。
#如我们需要匹配一个字符串中的文件名,test.py,可以用如下的表达式:
>>> print(re.findall(re.escape('test.py'),'I hava a test.py in the folder named test_py'))
['test.py']
>>> print(re.findall('test.py','I hava a test.py in the folder named test_py'))
['test.py', 'test_py']
start()、end()、span()
start()
返回匹配的起始位置。索引位置是从0开始计数的。end()
返回匹配结束的下一个位置。span()
返回匹配的区间,左闭右开。
>>> re.search(r'\d+', 'asdf13df234').start()
4
>>> re.search(r'\d+', 'asdf13df234').end()
6
>>> re.search(r'\d+', 'asdf13df234').span()
(4, 6)
来源:CSDN
作者:magic_jiayu
链接:https://blog.csdn.net/magic_jiayu/article/details/104086813