在python中通过内置的re库来使用正则表达式,它提供了所有正则表达式的功能。
一、写在前面:关于转义的问题
正则表达式中用“\”表示转义,而python中也用“\”表示转义,当遇到特殊字符需要转义时,你要花费心思到底需要几个“\”,所以为了避免这个情况,强烈推荐使用原生字符串类型(raw string)来书写正则表达式。
方法很简单,只需要在表达式前面加个“r”即可,如下:
r\'\d{2}-\d{8}\'
r\'\bt\w*\b\'
二、Re库常用的功能函数
1. re.match()
从字符串的起始位置匹配,匹配成功,返回一个匹配的对象,否则返回None
语法:re.match(pattern, string, flags=0)
pattern:匹配的正则表达式
string:要匹配的字符串
flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等;flags=0表示不进行特殊指定
可选标志如下:
修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志
示例:
不含标志位: >>> re.match(r\'\d{2}\',\'123\') <_sre.SRE_Match object; span=(0, 2), match=\'12\'> >>> re.match(r\'\d{2}\',\'ab123\') >>> print(re.match(r\'\d{2}\',\'ab123\')) None 含有标志位: >>> re.match(r\'a\',\'ab123\').group() \'a\' >>> re.match(r\'a\',\'Ab123\').group() Traceback (most recent call last): File "<pyshell#5>", line 1, in <module> re.match(r\'a\',\'Ab123\').group() AttributeError: \'NoneType\' object has no attribute \'group\' >>> re.match(r\'a\',\'Ab123\',re.I).group() \'A\'
2. re.search()
扫描整个字符串并返回第一个成功的匹配对象,否则返回None
语法:re.search(pattern, string, flags=0)
示例:
>>> re.search(r\'\d{2}\',\'Ab123\') <_sre.SRE_Match object; span=(2, 4), match=\'12\'> >>> re.search(r\'\d{2}\',\'Abcde\') >>> print(re.search(r\'\d{2}\',\'Abcde\')) None
可以看到match()和search()返回的时match对象(即匹配对象),可以通过group()方法获得匹配内容
>>> re.search(r\'\d{2}\',\'Ab12c34d56e78\').group()
\'12\'
>>> re.match(r\'\d{2}\',\'12c34d56e78\').group(0)
\'12\'
group() 同group(0)就是匹配正则表达式整体结果,也就是所有匹配到的字符
group()其实更多的结合分组来使用,即如果在正则表达式中定义了分组(什么是分组?参见正则表达式学习,一个左括号“(”,表示一个分组),就可以在match对象上用group()方法提取出子串来。后面会单独写一下group()和groups()的用法,这里先简单了解一下。
re.match与re.search的区别:
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配(注意:仅仅是第一个)
3. re.findall()
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表
注意: match 和 search 是匹配一次,而findall 匹配所有
>>> re.findall(r\'\d{2}\',\'21c34d56e78\')
[\'21\', \'34\', \'56\', \'78\']
4. re.finditer()
和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回.
示例:
>>> match = re.finditer(r\'\d{2}\',\'21c34d56e78\')
>>> for t in match:
print(t.group())
21
34
56
78
>>>
5. re.split()
根据正则表达式中的分隔符把字符分割为一个列表并返回成功匹配的列表.
示例:
>>> match = re.split(r\'\.|-\',\'hello-world.data\') # 使用 . 或 - 作为字符串的分隔符
>>> print(match)
[\'hello\', \'world\', \'data\']
字符串也有split方法,如下,作个对比:
字符串的split方法
>>> \'a b c\'.split(\' \') # b和c之间有3个空格
[\'a\', \'b\', \'\', \'\', \'c\']
如果用空格不好理解的话,可以换位x
>>> \'axbxxxc\'.split(\'x\')
[\'a\', \'b\', \'\', \'\', \'c\']
>>>
可以看到,单纯用字符串的split方法无法识别连续的空格,
用正则表示式如下:
>>> re.split(r\'\s+\', \'a b c\') # \s+ 表示匹配一个或多个空白符(\s表示匹配空白符,+表示重复1次或1次以上)
[\'a\', \'b\', \'c\']
>>>
6. re.sub()
用于替换字符串中的匹配项
语法: re.sub(pattern, repl, string, count=0)
pattern:正则中的模式字符串。
repl:替换的字符串,也可为一个函数。
string:要被查找替换的原始字符串。
count:模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
示例:
>>> match = re.sub(r\'a\', \'b\',\'aaccaa\') # 把字符串中的a都替换为b
>>> print(match)
bbccbb
>>>
7. re.compile()
compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,然后就可以用编译后的正则表达式去匹配字符串
语法如下:
>>> help(re.compile)
Help on function compile in module re:
compile(pattern, flags=0)
Compile a regular expression pattern, returning a pattern object.
>>>
pattern : 一个字符串形式的正则表达式
flags :可选,表示匹配模式,比如忽略大小写,多行模式等
示例:
>>> test_pattern = re.compile(r\'\d{2}\') # 编译一个正则表达式,并将其赋给一个变量 >>> m = test_pattern.match(\'12bc34\') # 使用编译后的正则表达式对象直接匹配字符串 >>> m <_sre.SRE_Match object; span=(0, 2), match=\'12\'> >>> test_pattern = re.compile(r\'a\w+\') # 生成一个正则表达式对象(这里是匹配以a开头的单词) >>> m = test_pattern.findall(\'apple,blue,alone,shot,attack\') # 使用findall()函数匹配所有满足匹配规则的子串 >>> m [\'apple\', \'alone\', \'attack\']
8. group()和groups()
一般用match()或search()函数匹配,得到匹配对象后,需要用group()方法获得匹配内容;同时也可以提取分组截获的字符串(正则表达式中()用来分组)
示例:
>>> pattern = re.compile(r\'^(\d{3})-(\d{3,8})$\') # 匹配一个3位数开头,然后一个-,然后跟着3-8位数字的字符串 >>> m = pattern.match(\'020-1234567\') >>> m <_sre.SRE_Match object; span=(0, 11), match=\'020-1234567\'> >>> m.group() # 显示整个匹配到的字符 \'020-1234567\' >>> m.group(0) # 同样是显示整个匹配到的字符 \'020-1234567\' >>> m.group(1) # 提取第1个分组中的子串 \'020\' >>> m.group(2) # 提取第2个分组中的子串 \'1234567\' >>> m.group(3) # 因为不存在第3个分组,所以这里会报错:没有这样的分组 Traceback (most recent call last): File "<pyshell#73>", line 1, in <module> m.group(3) IndexError: no such group >>> m.groups() (\'020\', \'1234567\') >>>
三、贪婪匹配和非贪婪匹配
贪婪匹配:匹配尽可能多的字符;(默认)
非贪婪匹配:匹配尽可能少的字符
例子:
>>> re.match(r\'^(\w+)(\d*)$\',\'abc123\').groups()
(\'abc123\', \'\')
>>> re.match(r\'^(\w+?)(\d*)$\',\'abc123\').groups()
(\'abc\', \'123\')
表达式1:
\w+表示匹配字母或数字或下划线或汉字并重复1次或更多次;\d*表示匹配数字并重复0次或更多次。
分组1中(\w)是贪婪匹配,它会在满足分组2(\d*)的情况下匹配尽可能多的字符(有点拗口),
因为分组2(\d*)匹配0个数字也满足,所以分组1就把所有字符全部匹配掉了,分组2只能匹配空了。
表达式2:在表达式后加个?即可进行非贪婪匹配,如上面的(\w+?),
因为分组1进行非贪婪匹配,也就是满足分组2匹配的情况下,分组1尽可能少的匹配,
这样的话,上面分组2(\d*)会把所有数字(123)都匹配,所以分组1匹配到(abc)