Python的模式匹配和正则表达式

1、简单介绍        

        正则表达式,简称regex,是文本模式的描述方法。例如:\d是一个正则表达式,表示一位数字字符,即任何一位0-9的数字。

        Python中所有正则表达式的函数都在 re 模块中。在交互环境中输入以下代码,导入该模块

import re

2、用正则表达式查找文本模式

2.1创建正则表达式和匹配Regex对象

        向 re.compile() 传入一个字符串值,表示正则表达式,它将返回一个Regex 模式对象。Regex对象的 search() 方法查找传入的字符串,寻找该正则表达式的所有匹配,如果字符串中没有找到该正则表达式模式, search() 方法将返回None。如果找到了, search() 方法将返回一个Match 对象。Match 对象有一个 group()方法,它返回被查找字符串中实际匹配的文本。例子:

import re

phoneNumRegex = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d')
mo = phoneNumRegex.search('My number is 415-596-4565')
print(f"Phone number found: {mo.group()}")

        输出结果:

Phone number found: 415-596-4565

2.2正则表达式匹配要点总结

        在Python中使用正则表达式有几个步骤:

        1.用  import re 导入正则表示模块

        2.用 re.compile() 函数创建一个Regex对象(记得使用原始字符串)

        3.向Regex 对象的 search()方法传入想查找的字符串。它返回一个Match对象.

        4.调用Match对象的group()方法,返回实际匹配文本的字符串。

3.用正则表达式匹配更多模式

3.1用括号分组

        若想将区号从电话号码中分离出来。添加括号将在正则表达式中创建“分组”:(\d\d\d)-(\d\d\d-\d\d\d\d)。然后使用 group()匹配对象方法,从一个分组中获取匹配的文本。

        正则表达式字符串中的第一对括号是第1组。第二对括号是第2组。向group()传入0或不传入参数,将返回整个匹配的文本。如果想要一次就获取所有的分组,请使用 groups()方法

例子:

import re

phoneNumRegex = re.compile(r'(\d\d\d)-(\d\d\d-\d\d\d\d)')
mo = phoneNumRegex.search('My number is 415-596-4565')
print(mo.group(0))
print(mo.group(1))
print(mo.group(2))
print(mo.groups())

areaCode, mainNumber = mo.groups()
print(f"{areaCode}-{mainNumber}")

输出结果:

415-596-4565
415
596-4565
('415', '596-4565')
415-596-4565

3.2用管道匹配多个分组

        字符 | 称为“管道”。希望匹配许多表达式中的一个时。就可以使用它。例如,正则表达式:r'Batman|Tina Fey'将匹配‘Batman’或‘Tina Fey’。

        如果Batman和Tina Fey都出现在被查找的字符串中,第一次出现的匹配文本,将作为Match对象返回。

import re

heroRegex = re.compile(r'Batman|Tina Fey')
mo1 = heroRegex.search('Batman and Tina Fey')
mo2 = heroRegex.search('Tina Fey and Batman')
print(mo1.group())
print(mo2.group())

运行结果:

Batman
Tina Fey

---------------------------------------------------------------------------------------------------------------------------------

如果你希望匹配 'Batman'、'Batmobile'、'Batcopter'和'Batbat'中任意一个。因为所有这些字符串都以Bat开始,所以如果能够只指定一次前缀,就很方便。

import re

batRegex = re.compile(r'Bat(man|mobile|copter|bat)')
mo = batRegex.search('Batmobile lost a wheel')
print(mo.group())
print(mo.group(1))

运行结果

Batmobile
mobile

3.3用问号实现可选匹配

        有时候,想匹配的模式是可选的。就是说,不论这段文本在不在,正则表达式都会认为匹配。字符?表明它前面的分组在这个模式中是可选的。

        例子1:

import re

batRegex = re.compile(r'Bat(wo)?man')
mo1 = batRegex.search('The Adventures of Batman')
mo2 = batRegex.search('The Adventures of Batwoman')
print(mo1.group())
print(mo2.group())

运行结果:

Batman
Batwoman

        利用前面电话号码的例子,可以让正则表达式寻找包含区号或不包含区号的电话号码

import re

phoneRegex = re.compile(r'(\d\d\d-)?(\d\d\d-\d\d\d\d)')
mo1 = phoneRegex.search('My number is 415-555-4242')
mo2 = phoneRegex.search('My name is 555-4242')
print(mo1.group())
print(mo2.group())

运行结果:

415-555-4242
555-4242

3.4用 * 号匹配零次或多次

* (星号)意味着”匹配零次或多次“,即星号之前的分组,可以在文本中出现任一次。它可以完全不存在,或一次又一次的重复。

import re

batRegex = re.compile(r'Bat(wo)*man')
mo1 = batRegex.search("The Adventures of Batman")
mo2 = batRegex.search("The Adventures of Batwoman")
mo3 = batRegex.search("The Adventures of Batwowowoman")
print(mo1.group())
print(mo2.group())
print(mo3.group())

运行结果:

Batman
Batwoman
Batwowowoman

3.5用加号匹配一次或多次

        * 号意味着”匹配零次或多次“,+(加号)则意味着”匹配一次或多次“。星号不要求分组出现在匹配的字符串中,但加号不同,加号前面的分组必须”至少出现一次“,这不是可选的。

import re

batRegex = re.compile(r'Bat(wo)+man')
mo1 = batRegex.search('The Adventures of Batwoman')
mo2 = batRegex.search('The Adventures of Batwowowoman')
print(mo1.group())
print(mo2.group())

运行结果:

Batwoman
Batwowowoman

正则表达式Bat(wo)+man 不会匹配字符串‘The Adventures of Batman’,因为加号要求 wo 至少出现一次。

3.6 用花括号匹配字符串

        如果想要一个分组重复特定次数,就在正则表达式中该分组的后面,跟上花括号包围的数字,例如,正则表达式(Ha){3}将匹配字符串‘HaHaHa’.

        除了一个数字,还可以指定一个范围,即在花括号中写下一个最小值、一个逗号和一个最大值。例如,正则表达式(Ha){3,5}将匹配字符串‘HaHaHa’、‘HaHaHaHa’和‘HaHaHaHaHa’

        也可以不写花括号中的第一个或第二个数字,不限定最小值或最大值。例如:正则表达式(Ha){3,}将匹配3次或更多次实例,正则表达式(Ha){,5}将匹配0到5次实例

3.7 贪心和非贪心匹配

        在字符串'HaHaHaHaHa'中,因为(Ha){3,5}可以匹配3个、4个或5个实例,你可能会有疑问,为什么在前面花括号的例子中,Match对象group()调用会返回'HaHaHaHaHa',而不是更短的可能结果。比较‘HaHaHa’和‘HaHaHaHa’也能有效匹配正则表达式(Ha){3,5}。

        python 的正则表达式默认是“贪心”的,这表示在有二义性的情况下,他们尽可能匹配最长的字符串。花括号的“非贪心”版本匹配尽可能最短的字符串,即在结束的花括号后跟着一个问号。

import re

greedyHaRegex = re.compile(r'(Ha){3,5}')
nongreedyHaRegex = re.compile(r'(Ha){3,5}?')
mo1 = greedyHaRegex.search("HaHaHaHaHa")
mo2 = nongreedyHaRegex.search("HaHaHaHaHa")
print(mo1.group())
print(mo2.group())

运行结果:

HaHaHaHaHa
HaHaHa

        注意,问号在正则表达式中肯有两种含义:声明非贪心匹配或表示可选分组,这两种含义是完全无关的。

4. findall()方法

        search()方法只能返回一个Match对象,包含被查找字符串中第一次匹配的文本,而findall()方法返回一组字符串,包含被查找字符串中的所有匹配。

        另外,findall()方法不是返回一个Match,而是返回一个字符串列表,只要在正则表达式中没有分组。如果在正则表达式中有分组,那么findall()方法将返回元组的列表。

import re

phoneRegex = re.compile(r'\d\d\d-\d\d\d-\d\d\d\d')
mo1 = phoneRegex.search('My number is 415-555-4242 and 212-425-3666')
mo2 = phoneRegex.findall('My number is 415-555-4242 and 212-425-3666')
phoneRegex = re.compile(r'(\d\d\d)-(\d\d\d)-(\d\d\d\d)')
mo3 = phoneRegex.findall('My number is 415-555-4242 and 212-425-3666')
print(mo1.group())
print(mo2)
print(mo3)

输出结果:

415-555-4242
['415-555-4242', '212-425-3666']
[('415', '555', '4242'), ('212', '425', '3666')]

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值