先介绍下最常见的元字符metacharacter:
literal 匹配字符串的值 foo
re1|re2 匹配正则式re1或re2 foo|bar
. 匹配一个任何字符(换行符除外) b.b
^ 匹配字符串开始 ^Dear
$ 匹配字符串结束 /bin/*sh$
* 匹配前面出现的零次或多次 [A-Za-z0-9]*
+ 匹配前面出现的一次或多次 [a-z]+\.com
? 匹配前面出现的零次或一次 goo?
{N} 匹配前面出现的正则式N次 [0-9]{3}
{M,N} 匹配前面出现的M次到N次 [0-9]{5,9}
[...] 匹配字符组里出现任意一个字符 [aeiou]
[...x-y...] 匹配从字符x到y中的任意一个字符 [A-Za-z]
[^...] 匹配不在字符集中的任意一个字符 [^A-Za-z]
(*|+|?|{})? 用于上面出现的任何“非贪婪”版本重复匹配次数 .*?[a-z]
(...) 匹配封闭括号中的正则式,并保存为子组 ([0-9]{3})?
接下来再介绍几个特殊字符:
\d 匹配任何一个数字字符,和[0-9]一样,\D是\d的反义词,表示任何一个非数字字符 data\d+\.txt
\w 匹配任何一个数字字母下划线字符,和[A-Za-z0-9_]相同,\W跟\w相反 [A-Za-z_]\w+
\s 匹配任何一个空白符,和[\n\t\r\v\f ]相同, \S是\s的反义
\b 匹配单词边界,\B是\b的反义 \bThe\b
\nn 匹配已保存的子组 price:\16
\c 逐一匹配特殊字符c,即取消它的特殊含义,按字面匹配 \. \\, \*
\A(\Z) 匹配字符串的起始(结束),跟^$是意义一样
再用一张图解释全部:
★ re.compile(strPattern[, flag]):
这个方法是Pattern类的工厂方法,用于将字符串形式的正则表达式编译为Pattern对象。
第二个参数flag是匹配模式,取值可以使用按位或运算符'|'表示同时生效,比如re.I | re.M。
另外,你也可以在regex字符串中指定模式,
比如re.compile('pattern', re.I | re.M)与re.compile('(?im)pattern')是等价的。
可选值有:
re.I(全拼:IGNORECASE): 忽略大小写(括号内是完整写法,下同)
re.M(全拼:MULTILINE): 多行模式,改变'^'和'$'的行为(参见上图)
re.S(全拼:DOTALL): 点任意匹配模式,改变'.'的行为
re.L(全拼:LOCALE): 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定
re.U(全拼:UNICODE): 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性
re.X(全拼:VERBOSE): 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释。
解释下“非贪婪”匹配?
当表示重复次数的元字符(*+?{m,n})单独使用时会尽量吸收更多的字符,一直吸到不匹配为止,榨干你丫的。哈哈哈。
而上面的(*+?{m,n})后面接了?后,就表示非贪婪匹配,匹配最短的,留下尽可能多的字符给后面的模式(如果存在)。
使用compile()编译正则表达式后,将正则式模式编译成regex对象,以后重复使用这个对象的时候可以提升执行的性能。
m = re.match('\w\w\w-\d\d\d', 'abc-123') if m is not None: print(m.group()) m = re.match('\w+\w+\w+-\d\d\d', 'abc-123') if m is not None: print(m.group()) m = re.match('\w+?\w+?\w+?-\d\d\d', 'abc-123') if m is not None: print(m.group())
哥原本以为那啥\w+会做贪婪匹配,弄的后面的两个\w+没得匹配,但是三个结果都一样啊。神马原因?
请看下面的:
m = re.match(r'(\w+)(\w+)(\w+)-\d\d\d', 'abcdefgh-123') if m is not None: print(m.group()) print(m.group(1)) print(m.group(2))
输出:
abcdefgh-123
abcdef
g
贪婪算法是:我前面的尽可能多的匹配更多,但是我会保证后面的也能匹配的前提下,自己捞的越多越好,这个就跟贪官一样,反正我给后面的那些平民百姓保本的东西,让他们饿不死就行,自己捞的越多越好,真他吗的黑心啊。
所以第一组中的(\w+)匹配了abcdef,留下两个gh给后面去抢。每人分一个,最小满足后面的。
来来来,再看几个例子:
import re __author__ = 'Xiong Neng' # group示例 data = 'Thu' patt1 = r'^(\w{3})' m = re.match(patt1, data) print(m.group(1)) patt2 = r'^(\w){3}' m = re.match(patt2, data) print(m.group(1)) # 贪婪匹配 data = "Sat Mar 21 09:20:57 2009::[email protected]::1237598457-6-9" # 获取最后的那三个连字符连起来的三个数, # 搜索比匹配更合适,因为不在开头 patt = r'\d+-\d+-\d+' print(re.search(patt, data).group()) # 打印出 1237598457-6-9 # 使用匹配,必须用到group patt = r'.+(\d+-\d+-\d+)' print(re.match(patt, data).group(1)) # 打印出 7-6-9,知道贪婪的厉害了吧。哈哈 # 接下来使用非贪婪操作符? patt = r'.+?(\d+-\d+-\d+)' print(re.match(patt, data).group(1)) # 打印出 1237598457-6-9 # 只获取三个数的中间那个数字: patt = r'-(\d+)-' print(re.search(patt, data).group()) # 打印-6- print(re.search(patt, data).group(1)) # 打印6 # 建议阅读Jeffrey E. F. Friedl编写的《精通正则表达式》(Mastering Regular Expression)
最后是几个小练习:
# 匹配所有整形字符串 patt = r'\d+' # 匹配长整形 patt = r'\d+[lL]' # 匹配浮点型 patt = r'(-?(\d+\.\d*|\d*\.\d+))([eE]-?\d+)?' print(re.match(patt, '-.2e-22').group()) print(re.match(patt, '23.23056e-23').group()) # 匹配所有复数 patt = r'(-?(\d+\.\d*|\d*\.\d+))([eE]-?\d+)?\s*[+-]\s*(\d+\.\d*|\d*\.\d+)([eE]-?\d+)?[jJ]' print(re.match(patt, '-.2e-22 - 32.E21J').group()) print(-.2e-22 - 32.E21J)
本人博客已搬家,新地址为:http://www.pycoding.com/