Python操作正则表达式

什么是正则表达式?

正则表达式(Regular Expression),又称规则表达式,通常被用来检索、替换那些符合某个模式(规则)的文本。许多程序设计语言都支持利用正则表达式进行字符串操作。

Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。re 模块使 Python 语言拥有全部的正则表达式功能。

正则表达式的使用对特殊字符进行了转义,所以如果我们要使用原始字符串,只需加一个 r 前缀。

元字符

正则表达式由一些普通字符和一些元字符(metacharacters)组成。普通字符包括大小写的字母和数字,而元字符则具有特殊的含义。下列为一些常见的元字符的使用说明。

匹配边界:
    ^     匹配行首
    $     匹配行尾
    
重复次数:
    ?    重复匹配0次或1次
    *     重复匹配0次或更多次
    +     重复匹配1次或更多次
    {n}   重复n次
    {n,}  重复n次或更多次
    {n,m} 重复n~m次
    
各种字符的表示:
    .     匹配除了换行符以外的任意字符串
    [a-z] 任意a-z的字母
    [abc] a,b,c中任意字符
    \d    匹配数字
    \D    匹配任意非数字的字符
    \w    数字,字母,下划线
    \W    匹配任意不是字母,数字,下划线的字符
    \s    空白字符(回车,制表,空格)
    \S    匹配任意不是空白符的字符
    \b    单词的边界
    \B    匹配不是单词开始和结束的位置
    
其他:
    [^123abc] 匹配除了123abc这几个字符以外的任意字符
    123|abc   匹配123或者abc 

Pattern 对象

compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 re 模块的查找方法使用。语法格式为:

pattern = re.compile(r'正则表达式','匹配模式')

# 常用的匹配模式:
#   re.S    可以让 . 匹配换行符
#   re.I    忽略大小写
#   re.M    多行匹配,影响 ^ 和 $ 

单次匹配

re 模块中,有两个方法,match 函数和 search 函数,这两个函数都是单次匹配,都返回一个
Match 对象。

re.match(pattern, string, start, end)
# pattern.match(string, start, end)

re.search(pattern, string, start, end)
# pattern.match(string, start, end)

# pattern  正则表达式对象
# string   要匹配的目标字符串
# start    要匹配的目标字符串的起始位置(可选)
# end为    要匹配的目标字符串的结束位置(可选)

"""案例"""

import re

pattern = re.compile(r'\w+', re.I)

string = 'I love python'

result = pattern.match(string, 2, 6)

print(result)
# <re.Match object; span=(2, 6), match='love'>

print(result.group())
# love

需要注意的是,match 函数 只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回 None,而 search 函数是匹配整个字符串,直到找到一个匹配。

import re

string = 'i am 18 !!!'

result1 = re.match(r'\d+', string)
result2 = re.search(r'\d+', string)

print(result1)
# None
print(result2.group())
# 18

分组

在Python中,正则表达式分组就是用一对圆括号“()”括起来的正则表达式,匹配出的内容就表示一个分组。即每个圆括号都是一个分组,从1开始。需要注意的是,有一个隐含的全局分组(就是0),也就是整个正则表达式。

import re

pattern = re.compile(r'name is (.*),age:(\d+)', re.I)

string = 'my name is 啊哈哈君,age:18 !'

result = pattern.search(string)

print(result)
# <re.Match object; span=(3, 22), match='name is 啊哈哈君,age:18'>
print(result.group())
# name is 啊哈哈君,age:18
print(result.group(1))
# 啊哈哈君
print(result.group(2))
# 18

Match 对象

关于match函数和search函数返回的match对象,也是有很多方法可以调用的。如上述案例的group函数,会返回被匹配的字符串。

# 返回被匹配的字符串,等价于group(0)
Match.group()  

# 返回第n个分组匹配的字符串,如果组号不存在,则返回indexError异常
Match.group(n)

# 返回组号为n到m组所匹配的字符串的元组,如果组号不存在,则返回indexError异常
Match.group(n,m) 

# 返回所有分组匹配的字符串的元组
Match.groups()

# 返回匹配开始的位置
Match.start()

# 返回匹配结束的位置
Match.end()

# 返回一个元组包含匹配 (开始,结束) 的位置
Match.span()

多次匹配

re 模块中的findall函数与finditer函数用于进行多次匹配。相信通过函数名,有些小伙伴就可以知道这两个函数的返回值。

import re

string = 'abcdefg'

result1 = re.findall(r'\w', string)
result2 = re.finditer(r'\w', string)

print(result1)
# ['a', 'b', 'c', 'd', 'e', 'f', 'g']
print(result2)
# <callable_iterator object at 0x000002452F017848>

由上述案例可看出,多次匹配与单次匹配的函数用法相同,也可以加start和end。只是findall函数返回的是一个列表,而finditer返回的是一个迭代器。

分割字符串

re 模块提供了一个spilt函数,用于通过正则表达式分割字符串,并返回一个列表。

import re

pattern = re.compile(r'\s', re.I)

string = 'python java c++'

result = pattern.split(string)

print(result)
# ['python', 'java', 'c++']

替换字符串

re 模块中的sub函数用于通过正则表达式替换字符串。格式为:

re.sub(pattern, repl, string, count)
# pattern.sub(repl, string, count)

# pattern  正则表达式或者正则对象
# repl     替换的字符串,也可为一个函数
# string   要被查找替换的原始字符串
# count    匹配后替换的最大次数,默认为0,表示替换所有的匹配

这个函数通过案例是很容易理解的。

import re

pattern = re.compile(r'python', re.I)

string = 'I Love Python, Python NB!'

result1 = pattern.sub('java', string)
result2 = pattern.sub('java', string, 1)

print(result1)
# I Love java, java NB!
print(result2)
# I Love java, Python NB!

当repl为函数时,函数的参数只能为match对象,并且这个函数必须有返回值,返回值的格式是字符串,将来就用这个字符串作为替换的内容。

import re

pattern = re.compile(r'python', re.I)


def func(matched):
    return matched.group()+' And Java'


string = 'I Love Python'

result = pattern.sub(func, string)

print(result)
# I Love Python And Java

贪婪模式与非贪婪模式

贪婪匹配:正则表达式一般趋向于最大长度匹配,也就是所谓的贪婪匹配。

非贪婪匹配:就是匹配到结果就好,取最少的匹配字符。

在Python中,默认是贪婪模式,而在正则表达式的量词后面直接加上一个问号?就会转换为非贪婪模式。

import re

string = 'i am 18 !'

result1 = re.search(r'\d+', string)
result2 = re.search(r'\d+?', string)

print(result1.group())
# 18
print(result2.group())
# 1

在上述案例中的正则为\d+,也就是匹配数字1次或多次。也就是说,在贪婪模式下,这个正则会往多的次数匹配,也就是优先多次,即匹配到了18,而非贪婪模式下,则会优先匹配1次,也就是优先匹配到了1,满足条件便会立刻返回结果。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容