Python 正则表达式

在处理字符串时,经常会有查找符合某些复杂规则的字符串的需求,正则表达式就是用来描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。

一、行定位符:行定位符用来描述子串的边界。“^”表示行的开始,“$”表示行的结尾。

1.要匹配的子串出现在字符串的开头部分,如:

^tm

该表达式表示要匹配的字符串是以tm开头的,如“tm is time”就可以匹配,而“time is tm”就不匹配。

2.要匹配的子串出现在字符串的结尾,如:

tm$

该表达式表示要匹配的字符串是以tm结尾的,如“time is tm”就可以匹配。

3.要匹配的子串出现在字符串的任意部分,可以直接写成:

tm

这样“tm is time”和“time is tm”就都可以匹配了。

二、元字符

1.先以一个例子引入一下元字符:

\bmr\w*\b

上面的正则表达式用于匹配以字母mr开头的单词,先从某个单词开始处(\b),然后匹配字母mr,接着时任意数量的字母或数字(\w*),最后是单词结束(\b)。该表达式可以匹配“mrsoft”、“mrbook”、“mr123mm”等等,但是与“amr”是不匹配的。

2.常用的元字符:

元字符说明
.匹配除换行符以外的任何字符
\w匹配字母、数字、下划线、汉字
\W匹配除字母、数字、下划线、汉字以外的字母
\s匹配单个空白符(包括<tab>键和换行符)
\S匹配除单个空白符(包括<tab>键和换行符)以外的所有字符
\d匹配数字
\b匹配单词的开始或结束,单词的分界符通常是空格、标点符号、换行
^匹配字符串的开始
$匹配字符串的结尾

三、限定符

1.先以一个例子引入限定符

在上面的例子中,使用(\w*)可以匹配任意数量的字母或数字。如果想匹配特定数量的数字,就需要用到限定符来实现该功能了。例如匹配11位的手机号可用如下的表达式:

^\d{11}$

2.常用的限定符:

限定符说明举例
?匹配前面的字符零次一次colou?r,该表达式可以匹配colour和color
+匹配前面的字符一次多次go+gle,该表达式可以匹配的范围从gogle到goo...gle
*匹配前面的字符零次多次go*gle,该表达示可以匹配的范围从ggle到go...gle
{n}匹配前面的字符n次go{2}gle,该表达式可以匹配google
{n,}匹配前面的字符至少n次go{1,}gle,该表达式可以匹配的范围从gogle到goo...gle
{n,m}匹配前面的字符至少n次,至多m次employe{0,2},该表达式可以匹配employ,employe,employee

四、字符类

正则表达式查找数字和字母是很简单的,因为已经有了对应这些字符集合的元字符(如 “\d”,“\w”),但是要匹配没有预定义元字符的字符集和(比如元音字母a、e、i、o、u),应该怎么办呢?

很简单,只需要在方括号里列出他们即可,像[aeiou]就可以匹配任何一个元音字符,[.?!]匹配标点符号(“.”或“?”或"!")。也可以轻松指定一个字符的范围,像[0-9]代表的含义与“\d”完全一样:一位数字;同理,[a-z0-9A-Z]也完全等同于"\w"(如果只考虑英文的话)

注:要想匹配给定字符串中任意一个汉字,可以使用“[\u4e00-\u9fa5]”;如果要匹配连续多个汉字,可以使用“[\u4e00-\u9fa5]+”。

五、排除字符:^

上面列出了匹配指定字符集合的字符串。现在反过来,匹配不符合指定字符集和的字符串。正则表达式中提供了"^"字符,这个字符前面提到过,是表示行的开始。而这里将其放到方括号中表示排除的意思,如:

[^a-zA-Z]

该表达式用于匹配一个不是字母的字符。

六、选择字符:|

举个例子:匹配身份证号,身份证号为15位或18位。如果是15位,则全部为数字;如果是18位,前17位全为数字,最后一位是数字或者或X或x。这个例子中包含着条件选择的逻辑,这就需要选择字符( | )来实现,该字符的意思是“或”。匹配身份证号的正则表达式为:

(^\d{15}$)|(^\d{18}$)|(^\d{17})(\d|x|X)$

七、分组:()

1.()的第一个作用就是可以改变限定符的作用范围,如:|,*,^。如下面的表达式:

(six|four)th

这个表达式的意思是匹配单词sixth或fourth,如果不使用小括号,就变成了匹配单词six或fourth了。

2.()的第二个作用是分组,也就是子表达式。如:

(\.[0-3]{1,3}){3}

这个表达式的意思就是对分组(\.[0-3]{1,3})进行3次重复操作。

八、转义字符:\,r

1.转义字符\:

正则表达式中的转义字符(\)和python中的大同小异,都是将特殊字符(如:“.”,“?”,"\"等)变为普通的字符。举个例子:用正则表达式匹配如“127.0.0.1”这样的IP地址,如果直接使用点字符,格式为:

[1-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}

这样显然不对,因为“.”可以匹配任意一个字符。这时,不仅是“127.0.0.1”这样的IP,连“127000001”这样的子串也会被匹配出来。所以在使用“.”时,需要使用转义字符(\),修改上面的格式为:

[1-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}

2.在python中使用正则表达式语法(关于r的使用):

在python中使用正则表达式时,是将其作为模式字符串使用的。例如,将匹配不是字母的一个字符的正则表达式表示为模式字符串,可以使用以下代码:

'[^a-zA-Z]'

而如果将匹配以字母m开头的单词的正则表达式转换为模式字符串,则不能直接在其两侧添加引号界定符,例如:'\bm\w*\b'是不正确的,而需要将“\”进行转义,转义后的结果为:'\\bm\\w*\\b‘。这样看起来是不是有点混乱呢?

由于模式字符串中可能包含大量的特殊字符和反斜杠,所以需要写为原生字符串,即在模式匹配串前加r或R,例如:

r'\bm\w*\b'

九、使用re模块实现正则表达式操作:

1.匹配字符串:使用re模块提供的match(),search(),findall()等方法。

1.1使用match()方法进行匹配:match()方法从字符串的开始进行匹配,如果匹配成功返回Match对象,否则返回None:

re.match(pattern,string[,flags])
  • pattern:模式字符串,由要匹配的正则表达式转换而来。
  • string:要匹配的字符串。
  • flags:可选参数,表示标志位,用于控制匹配方式,如区分大小写。常用的标志位如下:
标志说明
A或ASCII对于\w, \W, \b, \B, \d, \D, \s, \S只进行ASCII匹配(仅适用于python3.x)
I或IGNORECASE执行不区分字母大小写的匹配
M或MULTILINE将^和$用于包括整个字符串开始和结尾的每一行(默认情况下,仅适用于整个字符串的开始和结尾处)
S或DOTALL使用(.)字符匹配所以字符,包括换行符
X或VERBOSE忽略模式字符串中未转义的空格和注释

例如:匹配字符串是否以“mr”开头,不区分大小写:

import re
pattern=r'mr\w*'
string='Mr hello'
match=re.match(pattern,string,re.I)
print(match)                             #输出匹配结果
print('匹配值的起始位置:',match.start()) #获取匹配值的起始位置
print('匹配值的结束位置:',match.end())   #获取匹配值的结束位置
print('匹配位置的元组:',match.span())    #获取匹配位置的元组
print('要匹配的字符串:',match.string)    #获取进行匹配的字符串
print('匹配数据',match.group())          #获取进行匹配的字符串中可以匹配的子串

#运行结果
<re.Match object; span=(0, 2), match='Mr'>
匹配值的起始位置: 0
匹配值的结束位置: 2
匹配位置的元组: (0, 2)
要匹配的字符串: Mr hello
匹配数据 Mr

从上面的示例中可以看出,Match对象中包含了匹配值和匹配数据。其中:

  • Match中的start()方法用以获取匹配值的起始位置
  • end()方法:获取匹配值的结束位置
  • span()方法:获取匹配位置的元组
  • string()方法:获取进行匹配的字符串
  • group()方法:获取进行匹配的字符串中可以匹配的数据

1.2使用search()方法进行匹配:search()方法用于在整个字符串中搜索第一个匹配的值,如果匹配成功则返回Match对象,否则返回None:

re.search(pattern,string[,flags])

例如:搜索第一个以“mr”开头的字符串,不区分大小写

import re
string='helloMR_right Mr_Di mr_helon'
pattern='mr\w*'
match=re.search(pattern,string,re.I)
print(match)

#运行结果
<re.Match object; span=(5, 13), match='MR_right'>

1.3使用findall()方法进行匹配;findall()方法用于整个字符串搜索所有符合正则表达式的字符串,并以列表的形式返回。如果匹配成功,则返回包含匹配结果的列表,否则返回空列表:

re.findall(pattern,string[,flags])

例如:搜索以“MR”开头的字符串,不区分大小写:

import re
string='helloMR_right Mr_Di mR_helon'
pattern='mr\w*'
match1=re.findall(pattern,string,re.I)
match2=re.findall(pattern,string)
print(match1)
print(match2)

#运行结果
['MR_right', 'Mr_Di', 'mR_helon']
[]

如果在指定的模式字符串中,包含分组,则返回与分组匹配的文本列表,例如:

import re
pattern=r'[1-9]{1,3}(.[0-9]{1,3}){3}'
str1='126.0.0.1 197.165.1.77'
match=re.findall(pattern,str1)
print(match)

#运行结果
['.1', '.77']

从上面的结果中可以看出,并没有得到匹配的IP地址,这是因为在模式字符串中出现了分组,所以得到的结果是根据分组进行匹配的结果,即“(.[0-9]{1,3})”匹配的结果。如果想获取整个模式字符串的匹配的结果,可以将整个模式字符串使用一对小括号进行分组,然后在获取结果时,只取返回值列表的每个元素(列表中的元素是元组)的第一个元素。如下:

import re
pattern=r'([1-9]{1,3}(.[0-9]{1,3}){3})'
str1='126.0.0.1 197.165.1.77'
match=re.findall(pattern,str1)
print(match)
for item in match:
    print(item[0])

#运行结果
[('126.0.0.1', '.1'), ('197.165.1.77', '.77')]
126.0.0.1
197.165.1.77

2.替换字符串:sub()方法用于实现字符串的替换,语法格式如下:

re.sub(pattern,repl,string[,count][,flags])
  • pattern:表示模式字符串,由要匹配的正则表达式转换而来
  • repl:表示替换的字符串
  • string:要进行操作的原始字符串
  • count:可选参数,替换次数,默认为0,表示替换所有的匹配
  • flags:可选参数,表示标志位,用于控制匹配方式,如是否区分字母大小写。

例如:将一串字符中的手机号替换为“1*********”

import re
pattern='1[34578]\d{9}'
repl='1*******'
string='Mr Swan 小姐的手机号是17812345673'
result=re.sub(pattern,repl,string)
print(result)

#运行结果
Mr Swan 小姐的手机号是1*******

3.使用正则表达式分割字符串:split()方法用于正则表达式分割字符串,并以列表的形式返回。

re.split(pattern,string[,maxsplit][,flags])
  • pattern:·表示模式字符串,由要匹配的正则表达式转换而来
  • string:要匹配的字符串
  • maxsplit:可选参数,表示最大的拆分次数
  • flags:可选参数,表示标志位,用于控制匹配方式,如是否区分大小写

例如:

import re
pattern='1[34578]\d{9}'
string='Mr Swan 小姐的手机号是17812345673这不是座机'
result=re.split(pattern,string)
print(result)

#运行结果
['Mr Swan 小姐的手机号是', '这不是座机']

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值