本文来源,感谢分享
http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html
正则表达式当然不是python仅有,以下语法部分各语言适用,下文将针对python中re模块讲解适用方法
语法
语法 | 说明 | 表达式实体例 | 匹配的字符串 |
---|---|---|---|
一般字符 | 匹配自身 | abc |
abc |
. | 匹配任意除换行符"\n"外的字符, 在DOTALL模式中也能匹配换行符 | a.c |
abc |
[...] | "..."对应的位置可以是字符集中任意字符,可以逐个列出, 也可以给出范围,如[abc] 或者[a-c] 。第一个字符如果是^ 则表示取反,如[^abc] 表示不是abc的其他字符 |
a[bcd]e |
abe ace ade |
\ | 转义字符,如果有字符"."需要匹配,可以使用\. 或者[.]
|
a\.c a\\c
|
a.c a\c |
\d | 数字,相当于[0-9]
|
a\dc |
a1c |
\D | 非数字,相当于[^\d]
|
a\Dc |
abc |
\s | 空白字符,相当于[<blank>\t\r\n\f\v]
|
a\sc |
a<blank>c |
\S | 非空白字符,相当于[^\s]
|
a\Sc |
abc |
\w | 单词字符,相当于[A-Za-z0-9_]
|
a\wc |
abc |
\W | 非单词字符,相当于[^\w]
|
a\Wc |
a<空格>c |
* | 匹配前一个字符0次或者无限次 | abc* |
ab abccc |
+ | 匹配前一个字符1次或者无限次 | abc+ |
abc abccc |
? | 匹配前一个字符0次或者1次 | abc? |
ab abc |
{m} | 匹配前一个字符m次 | ab{2}c |
abbc |
{m,n} | 匹配前一个字符m至n次。m和n可以省略:若省略m,则匹配0至n次;若省略n,则匹配m至无限次 | ab{1,2}c |
abc abbc |
^ | 匹配字符串开头,在多行模式中匹配每一行的开头 | ^abc |
abc |
$ | 匹配字符串末尾,在多行模式中匹配每一行的末尾 | abc$ |
abc |
\A | 仅匹配字符串开头 | \Aabc |
abc |
\Z | 仅匹配字符串末尾 | abc\Z |
abc |
\b | 匹配\w 和\W 之间 |
a\b!bc |
a!bc |
\B | 相当于[^\b]
|
a\Bbc |
abc |
⎢ |
⎢ 左右的表达式任意匹配一个,先尝试左边的表达式,成功则跳过右边的表达式,如果⎢ 没有被包括在() 中,则范围是整个表达式 |
abc⎢def |
abc def |
(...) | "..."的内容将作为分组,从表达式左边开始每遇到一个( 编号+1,后可接数量词 |
(abc){2} a(123⎢456)c
|
abcabc a456c |
(?P<name>...) | 分组,除了原有的编号再指定一个额外的别名 | (?P<id>abc){2} |
abcabc |
<number> | 引用编号为<number>的分组匹配到的字符串 | (\d)abc\1 |
1abc1 5abc2 |
(?P=name) | 引用别名为<name>的分组匹配到的字符串 | (?P<id>\d)abc(?P=id) |
1abc1 5abc2 |
(?:...) | (...)的不分组版本,用于使用⎢ 或后接数量词 |
(?:abc){2} |
abcabc |
(?iLmsux) | iLmsux每个字符代表一个匹配模式,只能用在开头,可选多个 | (?i)abc |
AbC |
(?#...) | #后的内容将作为注释被忽略 | abc(?#comment)123 |
abc123 |
(?=...) | =之后的字符串需要匹配表达式才能成功匹配 | a(?=\d) |
a5 |
(?!...) | !之后的字符串内容需要不匹配表达式才能成功匹配 | a(?!\d) |
as |
(?(id/name)yes-pattern⎢no-pattern) | 如果编号为id或者别名为name的祖匹配到字符,则需要匹配yes-pattern,否则no-pattern | (\d)abc(?(1)\d⎢abc) |
1abc2 abcabc |
贪婪模式
贪婪模式:总是尝试匹配尽可能多的字符,python默认模式
非贪婪模式:总是尝试匹配尽可能少的字符
若使用正则表达式ab*
(非贪婪模式为ab*?
),用于查找"abbbc",结果如下:
贪婪:"abbb"(*
尝试匹配了3次)
非贪婪:"a"(*
尝试匹配了0次)
反斜杠的困扰
大多数编程语言和正则表达式都使用""作为转义字符。假如需要匹配文中的字符"",那么使用编程语言表示的正则表达式将需要4个反斜杠"\\",先由编程语言翻译成"\",再由正则表达式翻译成""
python中原生字符串应运而生,"\\"可以使用r"\"来表示(python将不对其进行反斜杠转义,而正则中仍需要转义),"\d"可写成r"\d"
re模块
通常的使用步骤
首先创建pattern对象,再使用pattern对象的实例方法
import re
pattern = re.compile(r'hello')
match = pattern.match('hello world!')
if match:
print match.group()
### 输出 ###
#hello
也可以使用模块方法用于完成正则表达式的功能,上面的例子可以简写为:
match = re.match(r'hello', 'hello world!')
if match:
print match.group()
### 输出 ###
#hello
re.compile(strPattern[, flag])方法
第一个参数为字符串
第二个参数flag是匹配模式,可省略
可选值有:
-
re.I
: 忽略大小写 -
re.M
: 多行模式,改变^
和$
的行为 -
re.S
: 点任意匹配模式,改变.
的行为 -
re.L
: 使预定字符类\w \W \b \B \s \S
取决于当前区域设定 -
re.U
: 使预定字符类\w \W \b \B \s \S \d \D
取决于unicode定义的字符属性 -
re.X
: 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释。以下两个正则表达式是等价的:
a = re.compile(r"""\d + # the integral part
\. # the decimal point
\d * # some fractional digits""", re.X)
b = re.compile(r"\d+\.\d*")
取值可以使用按位或运算符|
表示同时生效,比如re.I | re.M
也可以在regex字符串中指定模式,比如re.compile('pattern', re.I | re.M)
与re.compile('(?im)pattern')
是等价的。
Pattern
Pattern对象是一个编译好的正则表达式,通过Pattern提供的一系列方法可以对文本进行匹配查找
Pattern不能直接实例化,必须使用re.compile()进行构造
Pattern提供了几个可读属性用于获取表达式的相关信息:
- pattern: 编译时用的表达式字符串。
- flags: 编译时用的匹配模式。数字形式。
- groups: 表达式中分组的数量。
- groupindex: 以表达式中有别名的组的别名为键、以该组对应的编号为值的字典,没有别名的组不包含在内。
import re
p = re.compile(r'(\w+)(\w+)(?P<sign>.*)', re.DOTALL)
print "p.pattern:", p.pattern
print "p.flags:", p.flags
print "p.groups:", p.groups
print "p.groupindex:", p.groupindex
### 输出 ###
# p.pattern: (\w+)(\w+)(?P<sign>.*)
# p.flags: 16
# p.groups: 3
# p.groupindex: {'sign': 3}
match(),字符串开始部分相同即可成功
实例方法 | 模块方法 |
---|---|
match(string[, pos[, endpos]]) |
re.match(pattern, string[, flags]) |
-
match()
将从string的pos下标处起尝试匹配pattern,如果pattern结束时仍可匹配,则返回一个Match对象; - 如果匹配过程中pattern无法匹配,或者匹配未结束就已到达endpos,则返回None。
- pos和endpos的默认值分别为0和len(string)
- 模块方法
re.match()
无法指定这两个参数,参数flags用于编译pattern时指定匹配模式。 - 当pattern结束时若string还有剩余字符,仍然视为成功。想要完全匹配,可以在表达式末尾加上边界匹配符
$
search(),字符串中存在相同即可成功
实例方法 | 模块方法 |
---|---|
search(string[, pos[, endpos]]) |
re.search(pattern, string[, flags]) |
- 从string的pos下标处起尝试匹配pattern,如果pattern结束时仍可匹配,则返回一个Match对象
- 若无法匹配,则将pos加1后重新尝试匹配,直到pos=endpos时仍无法匹配则返回None。
- pos和endpos的默认值分别为0和len(string))
- re.search()无法指定这两个参数,参数flags用于编译pattern时指定匹配模式。
import re
pattern = re.compile(r'world')
match = pattern.search('hello world!')
if match:
print match.group()
### 输出 ###
# world
spilt()
实例方法 | 模块方法 |
---|---|
split(string[, maxsplit]) |
re.split(pattern, string[, maxsplit]) |
- 按照能够匹配的子串将string分割后返回列表
- maxsplit用于指定最大分割次数,不指定将全部分割。
import re
p = re.compile(r'\d+')
print p.split('one1two2three3four4')
### output ###
# ['one', 'two', 'three', 'four', '']
findall()
实例方法 | 模块方法 |
---|---|
findall(string[, pos[, endpos]]) |
re.findall(pattern, string[, flags]) |
- 搜索string,以列表形式返回全部能匹配的子串。
import re
p = re.compile(r'\d+')
print p.findall('one1two2three3four4')
### output ###
# ['1', '2', '3', '4']
finditer()
实例方法 | 模块方法 |
---|---|
finditer(string[, pos[, endpos]]) |
re.finditer(pattern, string[, flags]) |
- 搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。
import re
p = re.compile(r'\d+')
for m in p.finditer('one1two2three3four4'):
print m.group()
### output ###
# 1 2 3 4
sub()
实例方法 | 模块方法 |
---|---|
sub(repl, string[, count]) |
re.sub(pattern, repl, string[, count]) |
- 使用repl替换string中每一个匹配的子串后,返回替换后的字符串
- 当repl是一个字符串时,可以使用\id或\g<id>、\g<name>引用分组,但不能使用编号0
- 当repl是一个方法时,这个方法应当只接受一个参数(Match对象),并返回一个字符串用于替换(返回的字符串中不能再引用分组)。
- count用于指定最多替换次数,不指定时全部替换。
import re
p = re.compile(r'(\w+) (\w+)')
s = 'i say, hello world!'
print p.sub(r'\2 \1', s)
### output ###
# say i, world hello!
subn()
实例方法 | 模块方法 |
---|---|
subn(repl, string[, count]) |
re.sub(pattern, repl, string[, count]) |
- 返回 (sub(repl, string[, count]), 替换次数)。
import re
p = re.compile(r'(\w+) (\w+)')
s = 'i say, hello world!'
print p.subn(r'\2 \1', s)
### output ###
# ('say i, world hello!', 2)
Match
Match对象是一次匹配的结果,包含了很多关于此次匹配的信息,可以使用Match提供的可读属性或方法来获取这些信息
属性:
- string: 匹配时使用的文本
- re: 匹配时使用的Pattern对象
- pos: 文本中正则表达式开始搜索的索引
- endpos: 文本中正则表达式结束搜索的索引
- lastindex: 最后一个被捕获的分组在文本中的索引
- lastgroup*: 最后一个被捕获的分组的别名
方法:
- group([group1, …]):
- 获得一个或多个分组截获的字符串,指定多个参数时将以元组形式返回
- group1可以使用编号也可以使用别名
- 编号0代表整个匹配的子串;不填写参数时,返回group(0)
- 没有截获字符串的组返回None;截获了多次的组返回最后一次截获的子串
- groups([default]):
- 以元组形式返回全部分组截获的字符串
- 相当于调用group(1,2,…last)
- default表示没有截获字符串的组以这个值替代,默认为None。
- groupdict([default]):
- 返回以有别名的组的别名为键、以该组截获的子串为值的字典,没有别名的组不包含在内
- default含义同上。
- start([group]):
- 返回指定的组截获的子串在string中的起始索引(子串第一个字符的索引)
- group默认值为0
- end([group]):
- 返回指定的组截获的子串在string中的结束索引(子串最后一个字符的索引+1)
- group默认值为0
- span([group]): 返回(start(group), end(group))
- expand(template):
- 将匹配到的分组代入template中然后返回
- template中可以使用\id或\g<id>、\g<name>引用分组,但不能使用编号0
- \id与\g<id>是等价的,但\10将被认为是第10个分组,如果你想表达\1之后是字符'0',只能使用\g<1>0。
import re
m = re.match(r'(\w+) (\w+)(?P<sign>.*)', 'hello world!')
print "m.string:", m.string
print "m.re:", m.re
print "m.pos:", m.pos
print "m.endpos:", m.endpos
print "m.lastindex:", m.lastindex
print "m.lastgroup:", m.lastgroup
print "m.group(1,2):", m.group(1, 2)
print "m.groups():", m.groups()
print "m.groupdict():", m.groupdict()
print "m.start(2):", m.start(2)
print "m.end(2):", m.end(2)
print "m.span(2):", m.span(2)
print r"m.expand(r'\2 \1\3'):", m.expand(r'\2 \1\3')
### output ###
# m.string: hello world!
# m.re: <_sre.SRE_Pattern object at 0x016E1A38>
# m.pos: 0
# m.endpos: 12
# m.lastindex: 3
# m.lastgroup: sign
# m.group(1,2): ('hello', 'world')
# m.groups(): ('hello', 'world', '!')
# m.groupdict(): {'sign': '!'}
# m.start(2): 6
# m.end(2): 11
# m.span(2): (6, 11)
# m.expand(r'\2 \1\3'): world hello!