Python正则表达式入门

正则表达式

文本查找实例

正则表达式主要是让使用者指定要查找的“模式”,而不是死板地查找固定的内容。

不用正则表达式查找内容

例如我们要查找长沙区号的电话号码,那么我们就需要知道特征,比如0731-84802110,0731是长沙的区号,紧接着就是-短横,然后是8位数字,那么我们就必须要符合这样的格式,否则我们将找到错误内容。
比如我们不能找到的是0732-84802110,也不能是073184802110,更不能是0731-长沙号码,这样就会查找错误。
这样我们就必须要一步一步来。

def isPhoneNumber(text):
if len(text) != 13:
return False
if text[4] != '-':
return False
if text[0] != '0':
return False
if text[1] != '7':
return False
if text[2] != '3':
return False
if text[3] != '1':
return False
for i in range(5, 13):
if not text[i].isdecimal():
return False
return True
print(isPhoneNumber('text'))
print(isPhoneNumber('0731-84802110'))
print(isPhoneNumber('0731-8480211'))
print(isPhoneNumber('0732-84802110'))

以上只是一个粗糙的代码,输出结果为:

False
True
False
False

但是这是一种非常粗糙的查找方式,而且只能查找一种模式的电话号码,那么我们看看正则表达式。

正则表达式查找文本

基本方法流程

正则表达式,简称为regex,是文本模式的一种描述方法。
例如\d是一个正则表达式,表示一位数字字符,即任何一位0到9的数字,我们之前查找时可将文本视为0731-\d\d\d\d\d\d\d\d,这样其他字符串就不能匹配这样的内容了。
当然我们还可以用{}来表示匹配次数,如我们可将文本写为0731-\d{8}这样就不用打很多次\d了。
在使用正则表达式的之前,我们需要将python中的模块re导入:

import re

在查找时,我们需要创建一个Regex对象来匹配电话号码:

import re
phoneNumRegex = re.compile('0731-\d{8}')
mo = phoneNumRegex.search('我的电话号码是0731-84802110')
print(mo.group())

注意我们始终操作的是字符串,所以不要漏引号。
以上代码非常简洁,它以这样的步骤运行:

利用正则表达式匹配更多模式

括号分组

我们可以用括号对查找文本进行分组,例如(\d\d\d\d)-(\d\d\d\d\d)前一组为1组,后一组为2组,当我们找到一个匹配的文本时,我们向group()方法中传递参数1,2,0或不传入时,我们依次会得到1组,2组与所有分组。
如果我们用groups()方法,我们将得到一个包含所有组的元组,就本例而言将得到(\d\d\d\d,\d\d\d\d\d).
如果我们需要对括号进行查询,我们就需要用转义字符\。

管道匹配

字符 | 被称为“管道”,它表示一种的关系,我们如果利用这个字符查找,我们将有多种匹配,例如’batman | superman’我们将匹配batman或superman。
如果一句话中同时出现了两个内容,那么我们匹配到第一个出现的内容。

import re
phoneNumRegex = re.compile(r'0731 | 84802110')
mo1 = phoneNumRegex.search('我的电话号码是0731-84802110')
mo2 = phoneNumRegex.search('我的电话号码是84802110-0731')
mo1.group()
mo2.group()

我们将输出一下内容:

0731
84802110

我们可以复合使用,如(bat | super)man,这样我们也能同时匹配。

问号可选匹配

我们可以在字符串中使用?来匹配可选的内容,例如:如果我们想匹配man或者woman,那么我们可以写出(wo)?man,那么我们将能抓取到man与woman。
需要注意的是,两者同时出现的话,将优先按照文本顺序只挑出一个来。而且如果我们只查询woman的话,它也只会返回woman而不是man。

import re
phoneNumRegex = re.compile(r'(wo)?man')
mo = phoneNumRegex.search('woman and man')
print(mo.group(0))
mo = phoneNumRegex.search('man and woman')
print(mo.group(0))

这样我们就实现的可选匹配。

*星号多次匹配

星号相较问号相比,相应内容可以多次出现,例如:(wo)*man,如果我们输入wowowowoman,我们也能匹配得到,当然如果没有wo,它照样能匹配。

+加号多次匹配

+与*相比,前面的分组必须出现至少一次,除此之外,它与*几乎没有区别。

{}花括号匹配特定次数

{min,max}可以指定特定匹配次数范围,这是一个闭区间,如果只输入一个数字且没有逗号,那么将会只匹配该次数。这个时候我们将会引出一个问题,如果我们匹配’哈哈哈’而正则表达式写为‘哈{1,3}’,那么它返回的是哈还是哈哈还是哈哈哈呢?
解决这个问题我们要知道贪心与非贪心匹配

贪心指的是python默认条件下将匹配尽可能的字符串,此时上例我们将匹配到哈哈哈。
非贪心指的是匹配尽可能短的字符串。那么上例将匹配到哈。

由于python默认为贪心匹配,我们如果想使用非贪心匹配,需要在正则中 } 的末尾加上一个?以实现非贪心匹配。

findall()方法

findall()方法将返回一个包含所有匹配内容的列表。请注意,如果正则表达式里有分组,那么我们将会得到对应元组的列表。

字符分类

缩写字符分类表示
\d0到9的任何数字
\D除去0到9的数字以外的任何字符
\w任何字母、数字以及下划线的字符
\W除去\w匹配字符的任何字符
\s空格、制表符或换行符
\S除去\s匹配字符的任何字符

建立自己的字符分类

我们可以利用方括号来建立自己的字符分类,比如全部的元音字母[aeiouAEIOU],当我们用此建立一个Regex对象去查找文本的时候,我们将得到所有在文本中出现过的元音字母的列表。
方括号内不需要用转义字符转义来匹配特殊符号。
我们在字符分类的左方括号的后面加上 ^ 的时候,我们将匹配到除方括号内以外的所有字符,例如:[^aeiouAEIOU]

利用^和$来实现精准匹配

^ 字符和 $ 字符插入字符表示“必须以此开头”和“必须以此结尾”,例如’^hello’则表示文本必须以hello开头,如果两个符号合用,将实现完全精准匹配。
'^\d+$'这个正则表示从头至尾都是数字的字符串。

通配符

. 字符(英文句号)在正则中表示通配符,它匹配除了换行以外的所有字符。所以.at可以匹配mat,rat,cat等等。
如果用好搭配,就可以匹配任意字符,比如(.*)这个搭配可以匹配任意字符。

不区分大小写的匹配

我们在re.compile()方法中传入第二个参数即可实现大小写不区分的匹配。

robocop = re.compile(r'robocop',re.I)

传入这个re.I之后我们就能实现该效果。

用sub()方法实现文本替换

namesRegex = re.compile('Agent \w+')
namesRegex.sub('Sucker','Agent Alice find the Agent Bob')

我们将会得到以下输出:

Sucker find the Sucker

由此我们得到文本替换的方法。

多行正则

如果正则表达式过长,它的可读性就将降低,此时我们需要依赖注释对其进行解释,从而提高可读性。
比如:

phoneRegex = re.compile(r'''(
(\d{3}| \(\d{3}\))? #地区号码
(\s | - | \.)? #分隔符
\d{3} #前三个号码
(\s | - | \.)? #分隔符
\d{4} #最后四个数字
)''',re.VERBOSE)

re.VERBOSE作为参数传入可以实现对空格和换行的忽略,这样我们就能实现多行正则表达式。
如果你还想忽略大小写,注意不能传入多个参数,我们需要在第二个参数后使用 | 的操作符来实现多功能复合。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值