正则表达式对于初学者来说,要用好这个功能还是有点难度,也看了好久书加练习才掌握一些基础。对学到的一些东西还是写下来比较好一些,免得过几天又忘了。
常用符号:. * ? ()
常用方法: findall search sub
常用技巧
1 Python 正则式的基本用法
Python 通过标准库re模块支持正则表达式。
>>> import re
>>> string = "XXXIXXXLoveXXX"
>>> re.findall('XXX(.*?)XXX', string)
['I']
>>>
在python术语中,有两种主要方法完成模式匹配:serarching 和matching.
搜索:在字符串中任意部分中搜索匹配模式。
匹配:判断一个字符串是否能从起始位置全部或部分匹配某个模式。
常用正则符号字符如下图:
a. 基本规则
'.' 匹配所有字符
匹配除换行符 '\n' 外的所有字符。如果使用了 'S' 选项,匹配包括 '\n' 的所有字符。要明确的匹配一个'.',必须使用’\‘对它进行转义。
>>> s = """XXX IXXX""" >>> re.findall('.+', s) ['XXX', 'IXXX'] >>> re.findall('.+', s, re.S) ['XXX\nIXXX'] >>>
b. 对基本规则作限定(闭包操作符)
'*' 0 或多次匹配。常用.*(贪心算法)
>>> x = "abc2323sf23"
>>> re.findall('c.*s', x)
['c2323s']
>>>
'+' 1 次或多次匹配
>>> x = "abc2323sf23"
>>> re.findall('c\d+s', x)
['c2323s']
>>>
'?' 0 或 1 次匹配。常用.*?(非谈心算法)
>>> x = "abc2323sf23"
>>> re.findall('c\d?', x)
['c2']
>>> re.findall('c\d+?', x)
['c2']
>>> re.findall('c.*?', x)
['c']
‘{m}'精确匹配 m 次
‘{m,n}'匹配最少 m 次,最多 n 次
2. ()创建组
一对()和正则表达式一起使用可达到:
a. 对正则进行分组
b. 匹配子组
>>> s= 'XXXIXXXLOVEXXXYOU'
>>> re.findall('XXX(.*)XXX(.*)XXX(.*)', s)
[('I', 'LOVE', 'YOU')]
>>>
可以看到 findall 函数只返回了包含在 ’()’ 中的内容,而虽然前面和后面的内容都匹配成功了,却并不包含在结果中。
3. 常用函数
findall(pattern, string[,flags])
在目标字符串中查找符合规则的字符串。
第一个参数是规则,第二个参数是目标字符串,后面还可以跟一个规则选项。
返回结果结果是一个列表, 中间存放的是符合规则的字符串。如果没有符合规则的字符串被找到,就返回一个空列表。
常用规则选项
I IGNORECASE 忽略大小写区别。
L LOCAL 字符集本地化。这个功能是为了支持多语言版本的字符集使用环境的,比如在转义符/w ,在英文环境下,它代表[a-zA-Z0-9] ,即所以英文字符和数字。如果在一个法语环境下使用,缺省设置下,不能匹配 "é" 或 "ç" 。 加上这 L 选项和就可以匹配了。不过这个对于中文环境似乎没有什么用,它仍然不能匹配中文字符。
M MULTILINE 多行匹配。在这个模式下 ’^’( 代表字符串开头 ) 和 ’$’( 代表字符串结尾 ) 将能够匹配多行的情况,成为行首和行尾标记。
当我们调用findall()方法,我们可以非常简单的得到一个所有匹配模式的 列表,而不是得到对象。
>>> string = 'bird cat bird, cat dog' >>> s = re.findall(r'cat', string) >>> s ['cat', 'cat'] >>>
match 与 search
match( pattern, string, flags = 0)
search( pattern, string, flags = 0)
match函数尝试从字符串的开头开始对模式进行匹配,如果匹配成功,就返回一个匹配对象,如果失败返回空,匹配对象的group()方法可以用来显示那个成功的匹配。
search函数工作方式和match一样,这两个函数唯一的区别是: match 从字符串的开头开始匹配,如果开头位置没有匹配成功,就算失败了;而 search 会跳过开头,继续向后寻找是否有匹配的字符串。
常见例子:
对字符串'bird cat bird'调用mathch()方法,查找模式'bird'将会匹配:
>>> re.match(r'bird', 'cat bird cat') >>> string = 'bird cat bird' >>> s = re.match(r'bird', string) >>> s <_sre.SRE_Match object at 0x0000000003104D30> >>> s.group() 'bird' >>> s = re.match(r'cat', string) >>> s >>>
但是,如果我们对同一个字符串调用math()方法,查找模式'cat',则不会找到匹配。
而search()结果则不一样,search()方法会在它查找到一个匹配项之后停止继续查找,并返回其首次出现的位置。
>>> string = 'bird cat bird' >>> s = re.search(r'cat', string) >>> s <_sre.SRE_Match object at 0x0000000003104D30> >>> s.group() 'cat' >>>
分组示例:
即:上面提到的'()'号,对整个正则表达式的特定子串进行定位的能力。我们可以定义一个分组做为整个正则表达式的一部分,然后单独的对这部分对应匹配到的内容定位。
>>> string = "name: Tom, phone: 12344" >>> s = re.findall(r'(.*): (.*), phone: (\d+)',string) >>> s [('name', 'Tom', '12344')] >>> s = re.search(r'(.*): (.*), phone: (\d+)',string) >>> s <_sre.SRE_Match object at 0x0000000002F54AE0> >>> s.group(1) 'name' >>> s.group(2) 'Tom' >>> s.group(3) '12344' >>>
通过用圆括号来(字符‘(’和‘)’)包围正则表达式的特定部分,可以对内容进行分组然后对这些子组做单独处理。
总结:
1. 数量词的贪婪和非贪婪
贪婪:总是尽可能匹配可能多字符。
>>> import re >>> a = 'ab*' >>> re.findall(a, 'abbbc') ['abbb'] >>>
非贪婪:总是尝试尽可能少的字符。(常用)
>>> re.findall('ab*?', 'abbbc') ['a'] >>>
2. 反斜杠问题
与大多数编程语言相同,正则表达式里使用”\”作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符”\”,那么使用编程语言表示的正则表达式里将需要4个反斜杠”\\\\”:前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。
Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r”\\”表示。同样,匹配一个数字的”\\d”可以写成r”\d”。有了原生字符串,妈妈也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
3.Re 模块
re模块主要方法
re.compile(string[,flag]) #返回pattern对象
re.match(pattern, string[, flags])
re.search(pattern, string[,flags])
re.finadll(pattern, string[,flags])
pattern: pattern可以理解为一个匹配模式,需要利用re.compile方法获得。
例如:pattern = re.complie('aa*'), 通过compile方法编译生成一个pattern对象,然后我们利用这个对象来进行进一步的匹配。在刚才所说的另外几个方法例如 re.match 里我们就需要用到这个pattern了, 参数flag是匹配模式,取值可以使用按位或运算符’|’表示同时生效,比如re.I | re.M。
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): 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释。
a. re.match(pattern, string[, flags]
这个方法将会从string(我们要匹配的字符串)的开头开始,尝试匹配pattern,一直向后匹配,如果遇到无法匹配的字符,立即返回None,如果匹配未结束已经到达string的末尾,也会返回None。两个结果均表示匹配失败,否则匹配pattern成功,同时匹配终止,不再对string向后匹配。
>>> pattern = re.compile(r'hello') >>> result1 = re.match(pattern,'hello') >>> result1 <_sre.SRE_Match object at 0x0000000002D9E780> >>> result1.group() 'hello' >>> result1 = re.match(pattern,'nihao hello, ac') >>> result1.group() Traceback (most recent call last): File "<pyshell#13>", line 1, in <module> result1.group() AttributeError: 'NoneType' object has no attribute 'group' >>>
Match对象是一次匹配的结果,包含了很多关于此次匹配的信息,可以使用Match提供的可读属性或方法来获取这些信息.(下面部分copy百度现成)
1.string: 匹配时使用的文本。
2.re: 匹配时使用的Pattern对象。
3.pos: 文本中正则表达式开始搜索的索引。值与Pattern.match()和Pattern.seach()方法的同名参数相同。
4.endpos: 文本中正则表达式结束搜索的索引。值与Pattern.match()和Pattern.seach()方法的同名参数相同。
5.lastindex: 最后一个被捕获的分组在文本中的索引。如果没有被捕获的分组,将为None。
6.lastgroup: 最后一个被捕获的分组的别名。如果这个分组没有别名或者没有被捕获的分组,将为None。
方法:
1.group([group1, …]):
获得一个或多个分组截获的字符串;指定多个参数时将以元组形式返回。group1可以使用编号也可以使用别名;编号0代表整个匹配的子串;不填写参数时,返回group(0);没有截获字符串的组返回None;截获了多次的组返回最后一次截获的子串。
2.groups([default]):
以元组形式返回全部分组截获的字符串。相当于调用group(1,2,…last)。default表示没有截获字符串的组以这个值替代,默认为None。
3.groupdict([default]):
返回以有别名的组的别名为键、以该组截获的子串为值的字典,没有别名的组不包含在内。default含义同上。
4.start([group]):
返回指定的组截获的子串在string中的起始索引(子串第一个字符的索引)。group默认值为0。
5.end([group]):
返回指定的组截获的子串在string中的结束索引(子串最后一个字符的索引+1)。group默认值为0。
6.span([group]):
返回(start(group), end(group))。
7.expand(template):
将匹配到的分组代入template中然后返回。template中可以使用\id或\g、\g引用分组,但不能使用编号0。\id与\g是等价的;但\10将被认为是第10个分组,如果你想表达\1之后是字符’0’,只能使用\g0。
b. re.search(pattern, string[, flags])
search方法与match方法极其类似,区别在于match()函数只检测re是不是在string的开始位置匹配,search()会扫描整个string查找匹配,match()只有在0位置匹配成功的话才有返回,如果不是开始位置匹配成功的话,match()就返回None。同样,search方法的返回对象同样match()返回对象的方法和属性。
>>> pattern = re.compile(r'Hello') >>> match = re.search(pattern, 'WW,Hello,World') >>> match <_sre.SRE_Match object at 0x0000000002D9E780> >>> match.group() 'Hello' >>> match = re.search(pattern, 'WW,Helllo,World') >>> match >>>
c. re.findall(pattern, string[,flags])
搜索string,以列表形式返回全部能匹配的子串.
>>> pattern = re.compile(r'\d+') >>> re.findall(pattern, 'testx232xsdf3dsf3') ['232', '3', '3'] >>>