正则表达式

本文来源,感谢分享
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!
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容