在 Python 程序中,函数 match() 的功能是在字符串中匹配正则表达式,如果匹配成功,则返回 MatchObject 对象实例。
使用函数 match() 的语法格式如下所示:
re.match(pattern, string, flags=0)
各参数的具体说明如下:
参数pattern:匹配的正则表达式。
参数string:要匹配的字符串。
参数flags:标志位,用于控制正则表达式的匹配方式,如是否区分大小写、匹配多行等。参数 flags 的选项如表 3 所示。
表 3:参数 flags 的选项
参数
意义
re.I
忽略大小写
re.L
根据本地设置而更改\w、\W、\b、\B、\s 以及 \S 的匹配内容
re.M
多行匹配模式
re.S
如果使“.”元字符,也匹配换行符
re.U
匹配 Unicode 字符
re.X
忽略模式中的空格,并且可以使用塔“#”注释
注意:在 Python 中有多个内置模块,在每个内置模块中都会有很多内置函数。在平常描述时通常会直接使用函数名,而不会用模块前缀的方式。但是在程序中,必须使用函数的完整形式。例如,在上面的内容中,函数 match() 是内置模块 re. 的成员,所以在平常可以直接使用函数名的形式。但是在编写程序时,必须用完整的形式,即 re.match。
匹配成功后,函数 re.match() 会返回一个匹配的对象,否则返回 None。可以使用函数 group(num) 或函数 groups() 来获取匹配的表达式,如表 4 所示。
表 4:使用函数 group(num) 或函数 groups() 获取匹配的表达式
匹配对象方法
描述
group(num=0)
匹配整个表达式的字符串,可以一次向 group() 输入多个组号,这种情况下它将返回一个包含那些组所对应值的元组
groups()
返回一个包含所有组中字符串的元组
下面是如何运用 match()(以及 group())的一个示例。
>>> m = re.match('foo', 'foo') #模式匹配字符串
>>> if m is not None: #如果匹配成功,就输出匹配内容
... m.group()
... '
foo'
模式“foo”完全匹配字符串“foo”,也能够确认 m 是交互式解释器中匹配对象的实例。
>>> m #确认返回的匹配对象
下面是一个失败的匹配示例,它会返回 None。
>>> m = re.match('foo', 'bar') #模式并不能匹配字符串
>>> if m is not None: m.group() #单行版本的 if 语句
...
>>>
因为上面的匹配失败,所以 m 被赋值为 None,而且以此方法构建的 if 语句没有指明任何操作。对于剩余的示例,为了简洁起见,可省去 if 语句块。但是在实际操作中,最好不要省去,以避免 AttributeError 异常(None 是返回的错误值,该值并没有 group() 属性[方法])。
只要模式从字符串的起始部分开始匹配,即使字符串比模式长,匹配也能够成功。例如,模式“foo”将在字符串“food on the table”中找到一个匹配,因为它是从字符串的起始部分进行匹配的。
>>> m = re.match('foo', 'food on the table') # 匹配成功
>>>m.group()
'foo'
此时可以看到,尽管字符串比模式要长,但从字符串的起始部分开始匹配就会成功。
子串“foo”是从那个比较长的字符串中抽取出来的匹配部分,甚至可以充分利用 Python 原生的面向对象特性,忽略保存中间过程产生的结果。
>>>re.match('foo', 'food on the table').group()
'foo'
注意:在上述演示实例中,如果匹配失败,将会抛出 AttributeError 异常。
下面的实例文件 sou.py 演示了使用函数 match() 进行匹配的过程。
import re #导入模块
re
print(re.match('www', 'www.example.com').span()) #在起始位置匹配
print(re.match('net', 'www.example.com')) #不在起始位置匹配
执行后会输出:
(0, 3)
None
在正则表达式应用中,经常会看到关于电子邮件地址格式的正则表达式\w+@\w+.com,通常用于匹配这个正则表达式所允许的更多邮件地址。为了支持在域名前添加主机名称,如 www.example.com,仅允许 example.com 作为整个域名,必须修改现有的正则表达式。
为了表示主机名是可选的,需要创建一个模式来匹配主机名(后面跟着一个句点),使用问号?操作符来表示该模式出现零次或一次,然后按照如下实例文件 duoge.py 所示的方式将可选的正则表达式插入之前的正则表达式\w+@(\w+\.)?\w+\.com中。
import re
patt = '\w+@(\w+\.)?\w+\.com'
print(re.match(patt, 'guan@example.com').group())
print(re.match(patt, 'guan@www.example.com').group())
patt = '\w+@(\w+\.)*\w+\.com'
print(re.match(patt, 'guan@www.xxx.yyy.zzz.com').group())
从上述实例代码可以看出,表达式\w+@(\w+\.)?\w+\.com允许在.com前面有一个或者两个名称。第 5 行代码允许任意数量的中间子域名存在,读者需要注意这里的细节变化,此处将前面的?形式修改为\w+@(\w+\.)*\w+.com。这样仅使用字母数字字符的方式,并不能匹配组成电子邮件地址的全部可能字符。上面的正则表达式不能匹配诸如.com的域名,或者使用非单词\W字符组成的域名。
下面的实例文件 tiqu.py 演示了使用函数 group() 提取字母和数字字符的过程。
import re
m = re.match('(\w\w\w)-(\d\d\d)', 'abc-123')
print(m.group()) #完整匹配
print(m.group(1)) #子组1
print(m.group(2)) #子组2
print(m.groups()) #全部子组
在上述代码中,使用正则表达式能够提取字母、数字字符串和数字,方法是使用函数 group() 访问每个独立的子组,以及使用函数 groups() 获取一个包含所有匹配子组的元组。
执行后会输出:
abc-123
abc
123
('abc', '123')