Python 正则表达式笔记

总结一下在工作中常用到的关于Python正则的一些用法,主要无非就是匹配提取置顶信息,或者替换指定信息,不过都是re模块的用法

查找匹配

查找和匹配主要就是re.search()以及re.match()

  • match:从字符串的开始处匹配,匹配成功会返回match object,如果匹配不上返回None
  • search:只要又字串符合就匹配成功,返回match object,如果没有一个子串满足匹配则返回None
  • findall: 如果能匹配,返回所有的匹配结果list

下面会以代码介绍一下如何使用以及提取出匹配到的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re

__author__ = 'anonymous'

if __name__ == '__main__':
str1 = 'hello world, test test Test'
if not re.match('world', str1):
print '1:not match'
print '2:', re.match('hello', str1).group()
print '3:', re.match('.*test', str1).group()
print '4:', re.match('.*test', str1, re.I).group()
print '5:', re.search('test', str1, re.I).group()
pass

输出结果如下:

1
2
3
4
5
1:not match
2: hello
3: hello world, test test
4: hello world, test test Test
5: test
  • 1, 2 说明match()只会从开头开始匹配,如果不是在开头则无法匹配
  • 2, 3 说明如果要匹配的内容不是在字符串的开头,那么需要加.*或者类似的通配符
  • 3, 4 说明re.I表示的是忽略大小写,
  • 4, 5 可以看到search()函数则是在整个字符串里面去查找给定的模式,没有位置限制,但是只会匹配第一个,就算后面还有也不会输出来,所以只输出了一个test,后面的Test也没有输出来。

findall

如果想获取指定内容应该怎么做呢?这里介绍一下正则里面的(),用括号匹配出来的内容可以通过groups()提取,看下面的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re

__author__ = 'anonymous'

if __name__ == '__main__':
str1 = 'sfasfasfsfaname=hello phone=234123423 mail=23423@qq.com,hslfas7'

result = re.match(r'.*name=(\w*).*phone=(\d*) mail=(\d*@\w*.com).*', str1, re.I)

if result is not None:
print result.groups()
pass

看一下输出结果:

1
('hello', '234123423', '23423@qq.com')

可以看到,匹配结果被保存到了一个tuple里面,只要遍历这个tuple或者访问指定顺序的下标就可以获取相应的匹配结果了.
前面也说了,用search()匹配只会输出第一个匹配结果,而且上面的match()如果换成search(),调用groups()返回的结果和使用match()的结果是一样的,因为对于这个正则表达式来说,上面的匹配结果是第一个也是唯一一个。如果想返回字符串中所有出现的as应该怎么做呢?这个时候就需要用findall():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re

__author__ = 'anonymous'

if __name__ == '__main__':
str1 = 'sfasfasfsfaname=hello phone=234123423 mail=23423@qq.com,hslfas7'

result1 = re.findall(r'name=(\w*).*phone=(\d*) mail=(\d*@\w*.com)', str1, re.I)
result2 = re.findall(r'as', str1, re.I)
print result1
print result2
pass

程序的输出结果为

1
2
[('hello', '234123423', '23423@qq.com')]
['as', 'as', 'as']

可以看到findall()函数返回的是一个list,返回所有匹配的结果,如果正则里面有()提取内容,这写内容也会出现在里面,单独保存在一个tuple中.

正则分割

在Python中,如果想对一个字符串进行分割的话,只需要调用str的split方法就可以实现,但是这个split只能根据某个字符来进行分割的操作,如果要同时指定多个字符来进行分割的话,它就无法实现了。
好在re模块也提供了split这个方法来对字符串进行分割,而且这个方法更加强大,可以同时根据多个字符进行分割的操作,下面来看分别看一下str的split和re的split有什么不同的地方:

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re

__author__ = 'anonymous'

if __name__ == '__main__':
str1 = 'helloword,i;am\nalex'
str2 = str1.split(',')
print str2

str3 = re.split('[,|;|\n]', str1)
print str3

看看输出结果:

1
2
['helloword', 'i;am\nalex']
['helloword', 'i', 'am', 'alex']

这里就可以看到差别是啥了,正则分割确实功能更加强大也更加灵活,可以用正则模式分割一个字符串

正则替换

讲到正则分割,当然少不了正则replace(),同理字符串也有替换方法,但是只能替换指定的内容,如果想达到模糊替换,只能用正则,不过正则里面的替换方法不叫replace,叫sub().

1
2
3
4
5
6
7
8
9
10
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re

__author__ = 'anonymous'

if __name__ == '__main__':
str1 = 'Hello 111 is 222'
str2 = re.sub(r'\d+', '333', str1)
print str2

输出结果为:

1
Hello 333 is 333

正则查询表

平时记住一些常见的的正则用法,有些不太常用需要自己网上去查,这里整理记在一个表里,免得以后上网查:

正则速查表

字符 描述
\ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个向后引用、或一个八进制转义符。例如,n匹配字符n\n匹配一个换行符。串行\\匹配\\(则匹配(
^ 匹配输入字符串的开始位置。如果设置了RegExp对象的Multiline属性,^也匹配\n\r之后的位置。
$ 匹配输入字符串的结束位置。如果设置了RegExp对象的Multiline属性,$也匹配\n\r之前的位置。
  • |匹配前面的子表达式零次或多次。例如,zo*能匹配z以及zoo*等价于{0,}
  • |匹配前面的子表达式一次或多次。例如,zo+能匹配zo以及zoo,但不能匹配z+等价于{1,}
    ? |匹配前面的子表达式零次或一次。例如,do(es)?可以匹配doesdoes中的do?等价于{0,1}
    {n} |n是一个非负整数。匹配确定的n次。例如,o{2}不能匹配Bob中的o,但是能匹配food中的两个o
    {n,} |n是一个非负整数。至少匹配n次。例如,o{2,}不能匹配Bob中的o,但能匹配foooood中的所有o。o{1,}等价于o+o{0,}则等价于o*
    {n,m} |mn均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,o{1,3}将匹配fooooood中的前三个o。o{0,1}等价于o?。请注意在逗号和两个数之间不能有空格。
    ? |当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串ooooo+?将匹配单个o,而o+将匹配所有o
    . |匹配除\n之外的任何单个字符。要匹配包括\n在内的任何字符,请使用像(.|\n)的模式。
    (pattern) |匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用\(\)
    (?:pattern) |匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符(|)来组合一个模式的各个部分是很有用。例如industr(?:y|ies)就是一个比industry|industries更简略的表达式。
    (?=pattern) |正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,Windows(?=95|98|NT|2000)能匹配Windows2000中的Windows,但不能匹配Windows3.1中的Windows。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
    (?!pattern) |正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如Windows(?!95&#124;98&#124;NT&#124;2000)能匹配Windows3.1中的Windows,但不能匹配Windows2000中的Windows。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
    (?<=pattern) |反向肯定预查,与正向肯定预查类拟,只是方向相反。例如,(?<=95|98|NT|2000)Windows能匹配2000Windows中的Windows,但不能匹配3.1Windows中的Windows
    (?<!pattern) |反向否定预查,与正向否定预查类拟,只是方向相反。例如(?<!95|98|NT|2000)Windows能匹配3.1Windows中的Windows,但不能匹配2000Windows中的Windows
    x|y |匹配x或y。例如,z&#124;food能匹配zfood(z&#124;f)ood则匹配zoodfood

[xyz] |字符集合。匹配所包含的任意一个字符。例如,[abc]可以匹配plain中的a
[^xyz] |负值字符集合。匹配未包含的任意字符。例如,[^abc]可以匹配plain中的p
[a-z] |字符范围。匹配指定范围内的任意字符。例如,[a-z]可以匹配az范围内的任意小写字母字符。
[^a-z] |负值字符范围。匹配任何不在指定范围内的任意字符。例如,[^a-z]可以匹配任何不在az范围内的任意字符。
\b |匹配一个单词边界,也就是指单词和空格间的位置。例如,er\b可以匹配never中的er,但不能匹配verb中的er
\B |匹配非单词边界。er\B能匹配verb中的er,但不能匹配never中的er
\cx |匹配由x指明的控制字符。例如,\cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的c字符。
\d |匹配一个数字字符。等价于[0-9]
\D |匹配一个非数字字符。等价于[^0-9]
\f |匹配一个换页符。等价于\x0c\cL
\n |匹配一个换行符。等价于\x0a\cJ
\r |匹配一个回车符。等价于\x0d\cM
\s |匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]
\S |匹配任何非空白字符。等价于[^ \f\n\r\t\v]
\t |匹配一个制表符。等价于\x09\cI
\v |匹配一个垂直制表符。等价于\x0b\cK
\w |匹配包括下划线的任何单词字符。等价于[A-Za-z0-9_]
\W |匹配任何非单词字符。等价于[^A-Za-z0-9_]
\xn |匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,\x41匹配A\x041则等价于\x04&1。正则表达式中可以使用ASCII编码。
\num |匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,(.)\1匹配两个连续的相同字符。
\n |标识一个八进制转义值或一个向后引用。如果\n之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字(0-7),则n为一个八进制转义值。
\nm |标识一个八进制转义值或一个向后引用。如果\nm之前至少有nm个获得子表达式,则nm为向后引用。如果\nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若nm``均为八进制数字(0-7),则\nm将匹配八进制转义值nm。 \nml |如果n为八进制数字(0-3),且m和l均为八进制数字(0-7),则匹配八进制转义值nml。 \un |匹配n,其中n是一个用四个十六进制数字表示的Unicode字符。例如,\u00A9匹配版权符号(©)`。