Python 正则表达式

1. 标准库模块 re

Python3中使用re模块支持正则表达式(Regular Expression),需要定义一个用于匹配的模式(pattern)字符串,以及一个要匹配的字符串(string)
两种模式:
(1)如果做一次简单的文本匹配/搜索操作的话,可以直接使用 re 模块级别的函数
(2)如果你打算做大量的匹配和搜索操作的话,最好先编译正则表达式,然后再重复使用它

1.1 使用match()从字符串开头开始匹配

格式:返回值 = re.match( ' 正则模式' ,' 字符串 ' )
格式:返回值 = re.compile('正则模式').match('字符串')
如果字符串是以正则表达式开头,则表明匹配成功,返回匹配到的对象,比<_sre.SRE_Match object; span=(0, 2), match='My'>,如果匹配失败,返回None

1.2 使用search()寻找首次匹配

格式:返回值 = re.search( ' 正则模式' ,' 字符串 ' )
格式:返回值 = re.compile('正则模式').search('字符串')
如果字符串中有多个地方与正则表达式匹配的话,search()方法返回第一次匹配到的结果

1.3 使用findall()或finditer()寻找所有匹配

格式:返回值 = re.findall( ' 正则模式' ,' 字符串 ' )
格式:返回值 = re.compile('正则模式').findall('字符串')
格式:返回值 = re.finditer( ' 正则模式' ,' 字符串 ' )
格式:返回值 = re.compile('正则模式').finditer('字符串')
findall()方法会搜索文本并以列表形式返回所有的匹配。
如果想以迭代方式返回匹配,可以使用finditer()方法来代替

1.4 使用sub()替换匹配

格式:返回值 = re.sub('被匹配的模式', '替换模式', '字符串 ' )

2 正则表达式语法

2.1 基本模式

语法 说明 模式示例 匹配
普通字符 普通的文本值代表自身,用于匹配非特殊字符 ab ab
. 匹配除换行符\n以外的任意一个字符。如果要匹配多行文本,可以指定re.DOTALL标志位 ab. 匹配abc或abC,不匹配ab,因为b后面一定要有一个字符
\ 转义字符,比如要匹配点号.本身,需要转义它\.,如果不转义,.将有上一行所示的特殊含义 ab\. 匹配ab.com,不匹配abc
[] 匹配中括号内的一个字符 1. 中括号内的字符可以全部列出,如[abc]表示匹配字符abc 2. 也可以使用-表示范围,如[a-z]表示匹配所以小写字母中的任意一个字符 3. 本文后续要介绍的如*+等特殊字符在中括号内将失去特殊含义,如[*+()]表示匹配字符*+() 4. 本文后续要介绍的特殊字符集如\d\w等也可以放入此中括号内,继续保持特殊含义 5. 如果中括号内的字符序列前面有一个^,表示不匹配中括号内的任何一个字符,如[^0-9]表示不匹配数字,a[^0-9]c不匹配a1c,但会匹配abc 6. 要匹配字符],可以转义它,或者把它放在中括号内的首位,如a[()[\]{}]ca[]()[{}]c都可以匹配到a]c a[0-9]b a1b或a2

2.2 特殊字符集

语法 说明 模式示例 匹配
\d 匹配任意一个数字字符,等价于[0-9] a\db a1b
\D 匹配任意一个非数字字符,等价于[^0-9] a\Db aAb
\s 匹配任意一个空白字符,等价于[ \t\n\r\f\v] a\sb a b
\S 匹配任意一个非空白字符,等价于[^ \t\n\r\f\v] a\Sb aAb
\w 匹配任意一个 alphanumeric character,等价于[a-zA-Z0-9_] a\wb azb或aZb或a1b或a_b
\W 匹配任意一个 non-alphanumeric character,等价于[^a-zA-Z0-9_] a\Wb a-b或a b

2.3 数量

说明: 表格中 斜体 的 prev 表示 1. 单个字符如b 2. 或者复杂的表达式如(abc)或(.|\n)(这是分组的功能

语法 说明 模式示例 匹配
prev* 匹配0个或多个 prev,尽可能多地匹配,贪婪模式,等价于{0,} ab* a或ab或abb或abbb,注意是匹配字符a后面跟0个或多个字符b
prev*? 匹配0个或多个 prev,尽可能少地匹配,非贪婪模式 ab*? a,非贪婪模式下匹配0个字符b
prev+ 匹配1个或多个 prev,尽可能多地匹配,贪婪模式,等价于{1,} ab+ ab或abb或abbb
prev+? 匹配1个或多个 prev,尽可能少地匹配,非贪婪模式 ab+? ab,非贪婪模式下匹配1个字符b
prev? 匹配0个或1个 prev,尽可能多地匹配,贪婪模式,等价于{0,1} ab? a或ab
prev?? 匹配0个或1个 prev,尽可能少地匹配,非贪婪模式 ab?? a,非贪婪模式下匹配0个字符b
prev{m} 匹配m个连续的 prev a{3} aaa
prev{m,n} 匹配m到n个连续的 prev ,尽可能多地匹配,贪婪模式。n可选,如果不指定,则表示m到无穷多个连续的 prev a{3,5} aaa或aaaa或aaaaa
prev{m,n}? 匹配m到n个连续的 prev ,尽可能少地匹配,非贪婪模式 a{3,5}? aaa

2.4边界

语法 说明 模式示例 匹配
^prev 匹配以 prev 开头的字符串(脱字符)。多行文本中,默认只会匹配第一行的开头位置,如果设置了re.MULTILINE标志位,则也会匹配换行符之后的开头位置 ^ab abcd
prev$ 匹配以 prev 结尾的字符串。多行文本中,默认只会匹配最后一行的结尾位置,如果设置了re.MULTILINE标志位,则也会匹配换行符之前的结尾位置 ab$ 只匹配ab。如果是.*ab$则会匹配123ab,否则使用ab\Z
\b 单词边界。Matches the empty string, but only at the beginning or end of a word. A word is defined as a sequence of word characters. Note that formally, \b is defined as the boundary between a \w and a \W character (or vice versa), or between \w and the beginning/end of the string. 注意: \b在Python中默认会被转义为\x08表示退格,需要将整个正则表达式指定为原始字符串(在前面加个r),即r'\bfoo\b' r'\bfoo\b' 请使用re.findall()测试 匹配foo或foo.或(foo)或bar foo baz,但不匹配foobar或foo3
\B 非单词边界。Matches the empty string, but only when it is not at the beginning or end of a word. \B is just the opposite of \b. py\B 匹配python或py3或py2,但不匹配py或py.或py!
\A Matches only at the start of the string. \Aab abcde
\Z Matches only at the end of the string. ab\Z 123ab

2.5 分组

语法 说明 模式示例 匹配
(expr) 将小括号内的表达式作为一个分组,后面可以接表示数量的特殊字符。每个分组的编号从1开始递增,后续可以使用\1、\2这样引用分组匹配到的内容 a(bc)?d ad或abcd,不匹配abcbcd
expr1 │expr2 匹配 expr1 或 expr2 ,a│b│c等价于[abc],都表示匹配字符a或b或c。从左至右,如果匹配了某个表达式,则跳过后续表达式。expr1 │ expr2表示作用于整个待匹配的字符串,而(expr1│expr2)加入小括号内表示分组,不是整个字符串 p(i│u)g pig或pug
\1 引用编号为1的分组匹配到的字符串,同理\2表示引用第2个分组。注意: 此时为了不让Python自动将\1转义为\x01,需要将整个正则表达式指定为原始字符串(在前面加个r),即r'a(\d)b\1c' r'a(\d)b\1c' a3b3c
(?P<NAME>expr) 类似于(expr),同时给分组指定了一个别名NAME,注意是大写的字母P r'a(?P<quote>\d)b\1c' a3b3c
(?P=NAME) 引用别名为NAME的分组,当然也可以继续使用编号的形式引用分组如\1,此时要加r指定为原始字符串 a(?P<quote>\d)b(?P=quote)c 或 r'a(?P<quote>\d)b\1c' a3b3c

引用命名的分组:

当使用match()search()时,所有的匹配会以m.group()的形式返回到对象m中。如果你用括号将某一模式包裹起来, 括号中模式匹配得到的结果归入自己的分组group(无名称)中,而调用 m.groups() 可以得到包含这些匹配的元组

2.6 扩展语法

Python3中的正则表达式,以(?开头的都是一些扩展语法,比如上面学过的(?P<NAME>expr)和(?P=NAME),还有一些常用的:

语法 说明 模式示例 匹配
(?:expr) 非捕获组。如果分组后续要被\1这样的形式引用,使用(expr),这叫捕获组,后面可以接表示数量的特殊字符。如果不想分组被引用,就使用(?:expr),这叫非捕获组,后面可以接表示数量的特殊字符 a(?:\d)+bc,此时不支持引用分组,像r'a(?:\d)+b\1c'这样的属于语法错误 a333bc
prev(?=next) 如果后面为 next,则返回 prev ab(?=\d) 如果ab后面紧跟一个数字,则匹配,比如ab3,返回ab
prev(?!next) 如果后面不是 next,则返回 prev ab(?!\d) 如果ab后面不是紧跟一个数字,则匹配,比如abc,返回ab
(?<=prev)next 如果前面为 prev,则返回 next (?<=\d)ab 如果ab前面是一个数字,则匹配,比如1ab,返回ab
(?<!\d)ab 如果前面不是 prev,则返回 next (?<!\d)ab 如果ab前面不是一个数字,则匹配,比如Aab,返回ab

Python支持的其它正则表达式的标志位flags:

re.A: 或re.ASCII,使\w/\W/d/\D/\s/\S/\b/\B只匹配ASCII字符,不匹配Unicode字符。
re.I: 或re.IGNORECASE,忽略大小写,[A-Z]会匹配小写字母。
re.M: 或re.MULTILINE,多行模式,改变^或$的默认行为。
re.S: 或re.DOTALL,Make the.special character match any character at all, including a newline; without this flag, .will match anything except a newline。
re.U: 或re.UNICODE,默认使用此标志位,\w/\W/d/\D/\s/\S/\b/\B会匹配Unicode字符,如果指定了re.A标志,则re.U失效。
re.X: 或re.VERBOSE,允许整个正则表达式写成多行,忽略空白字符,并可以添加#开头的注释,这样更美观。

注:.|\n匹配所有字符,或者指定re.DOTALL标志位

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

推荐阅读更多精彩内容