Python中正则表达式的简单用法

  • 我们经常在写代码的时候,想要获取指定元素,一个万能的方法就是使用正则表达式来提取。但是对于正则表达式很多人觉得很复杂,各种符合看的都头晕,再加上网上很多资料都没系统介绍,就更加搞不懂了。因此我想写这一篇关于正则表达式的文章,来将这个看起来很高大上的东西尽量给大家说清道明。
    首先,正则表达式不是Python独有的,很多语言都有正则表达式,它是一个处理字符串的强大工具,有它自己的语法结构,在Python中,自带的有专门的正则表达式模块,即re模块。
  1. 在讲正则表达式的语法结构之前,我们先来看下关于正则表达式的一些常用的匹配规则
模式描述
\w匹配字母,数字及下划线
\W匹配非字母,数字及下划线的字符
\s匹配任意空白字符,等价于[\t\n\r\f]
\S匹配任意非空字符
\d匹配任意数字,即[0-9]
\D匹配任意非数字的字符
\A匹配字符串的开头
^匹配一行字符串的开头
$匹配一行字符串的结尾
.匹配除换行符外的任意字符
*匹配0个或多个表达式
+匹配1个或多个表达式
?匹配0次或1次前面的表达式,若要匹配?则用?表示
()匹配括号中的表达式,也表示一个组
  1. 匹配方法 Python中常用的正则表达式的方法有3种,分别为:
    match():从字符串的开头开始匹配,若匹配则返回匹配成功的结果,若不匹配则返回None
    search():通过扫描整个字符串来进行匹配,若匹配成功则返回第一个匹配的结果,若不匹配则返回None
    findall():通过扫描整个字符串来进行匹配,如果匹配成功则将所有匹配的结果返回,若未成功匹配则返回None
    接下来我们以match()方法来进行实例操作。
    在匹配方法中,如match(),第一个参数传入正则表达式,第二个参数传入要匹配的字符串。search()和findall()方法也是一样。
    re.match(正则表达式,待匹配的字符串)
  • 例1 匹配规则的简单运用:
import  re
data = 'zhangsan 1234567 beijingshi '
result = re.match('^zhangsan\s\d{7}\s\w{10}', data)
print(result)

上例中关于字符串的正则表达式可以写为:
^zhangsan\s\d{7}\s\w{10}
根据匹配规则,开头字符串为”zhangsan",因此可以写为‘zhangsan’(或者是z也行);后面是空格,则用’\s’来匹配,再后面是数字,用’\d’来匹配,由于有7个数字,因此可将‘\d\d\d\d\d\d\d’缩写成’\d{7}’,后面继续是空格,用’\s’匹配,最后是10个字符,可用’\w{10}'来匹配。
上述程序的运行结果为:

/Users/Desktop/Code/test/text2.py
<_sre.SRE_Match object; span=(0, 27), match='zhangsan 1234567 beijingshi'>

Process finished with exit code 0

表示匹配成功。

  • 例2 匹配并提取目标数据:
import  re
data = 'name:zhangsan tel:1234567 addr:beijingshi '
result = re.match('^name:(\w{8})\stel:(\d{7})\saddr:(\w{10})', data)
print(result)
print(result.group())
print(result.group(1))
print(result.group(2))
print(result.group(3))

运行结果为:

/Users/Desktop/Code/test/text2.py
<_sre.SRE_Match object; span=(0, 41), match='name:zhangsan tel:1234567 addr:beijingshi'>
name:zhangsan tel:1234567 addr:beijingshi
zhangsan
1234567
beijingshi

Process finished with exit code 0

如上述例子所示,当我们想要获取字符串中某些字符的时候,我们可以用()括号将想要提取的字符括起来,()括号实际上标识了一个子字符串的起始位置和结束位置,被标记的每个子字符串会一次对应每一个组,然后我们可以调用group()方法然后传入分组的索引即可获取指定的子字符串,如果不加索引,则输出整个匹配的结果。
注意:索引是从1开始的,不是从0开始。

  • 例3: 通用匹配
    通过之前两个例子我们发现,如果根据每个字符一一对应的关系去写正则表达式,这样写会很麻烦,并且写多了有时候看的也头晕。因此我们接下来介绍一种通用的写法,它会使正则表达式写起来简单明了很多,那就是
    .* (点星) 根据之前的匹配规则,我们发现
    .(点)是匹配除换行符外的任意字符,*(星)是代表匹配前面的字符无限次,因此将他们组合在一起就可以匹配任意字符了。
    下面我们将例1中的正则表达式做一下修改: 将正则表达式写为:^z.*shi
import  re
data = 'zhangsan 1234567 beijingshi'
result = re.match('^z.*shi', data)
print(result)

运行结果为:

/Users/Desktop/Code/test/text2.py
<_sre.SRE_Match object; span=(0, 27), match='zhangsan 1234567 beijingshi'>

Process finished with exit code 0

我们发现完全可以正确匹配,但是正则表达式精简了很多,我们可以将一些不重要的匹配信息都可以用.*来代替。
通过例3我们知道了一种通用匹配规则,用它可以简化很多正则表达式的写法,那么是不是这个方法就是一个万能的呢?我们接下来了看一下例4.

  • 例4 贪婪匹配:
import  re
data = 'name:zhangsan tel:1234567 addr:beijingshi'
result = re.match('^n.*(\d+).*', data)
print(result)
print(result.group(1))

我们想要获取data中的tel的值,即获取’1234567’,根据通用匹配规则,我么将正则表达式写为:
^n.(\d+).
其中^n是匹配开头,由于要匹配的是多个数字,则将需要匹配的数字正则表达式写为(\d+),其余的都用通用匹配规则.*来表示。
我们来看一下运行结果:

/Users/Desktop/Code/test/text2.py
<_sre.SRE_Match object; span=(0, 41), match='name:zhangsan tel:1234567 addr:beijingshi'>
7

Process finished with exit code 0

根据运行结果,我们发现我们已经成功匹配到了该字符串,但是输出到结果并不是我们想要的‘1234567’,输出的结果只有一个数字’7’,这是为什么呢?
这里就涉及到贪婪匹配与非贪婪匹配到问题了。.*是贪婪匹配,它会尽可能匹配多的字符(比较贪婪)。正则表达式中.*后面是(\d+),+表示的是匹配一个或多个表达式,\d+表示匹配一个或多个数字(至少1个),但是由于没有具体说明要匹配多少个数字,前面的.*就会一直匹配,直到满足\d+的最低匹配条件(匹配一个数字),因此前面的.将数字‘123456’都给匹配了,留给(\d+)的就只剩下一个’7’了,因此最终运行结就只有数字’7’了。
那么避免出现这种情况的方法就是采用非贪婪匹配的方式。非贪婪匹配的写法就是在贪婪匹配的后面加一个?问号,即.
?(点星问号)
将上述代码中贪婪匹配换成非贪婪匹配后,我们看一下结果是怎样的。

import  re
data = 'name:zhangsan tel:1234567 addr:beijingshi'
result = re.match('^n.*?(\d+).*', data)
print(result)
print(result.group(1))

运行结果:

/Users/Desktop/Code/test/text2.py
<_sre.SRE_Match object; span=(0, 41), match='name:zhangsan tel:1234567 addr:beijingshi'>
1234567

Process finished with exit code 0

采用非贪婪匹配后,发现能正常匹配到我们想要的数据了。
非贪婪匹配则是匹配尽可能少的字符,上例中当.?匹配到tel后面的冒号时,再往后就是数字了,恰好可以跟\d+匹配,那么.?则停止匹配,剩下的交给\d+去匹配后面的数字。因此我们可以得到想要的‘1234567’了。
在做匹配的时候,我们是不是只采用非贪婪匹配就“万事大吉”了呢?我们接下来看一下例5。

  • 例5: 我们想要获取addr后面的值,即‘beijingshi’
import  re
data = 'name:zhangsan tel:1234567 addr:beijingshi'
result1 = re.match('^n.*?addr:(.*?)', data)
result2 = re.match('^n.*?addr:(.*)', data)
print(result1)
print('result1 ',result1.group(1))
print('result2 ',result2.group(1))

运行结果为:

/Users/Desktop/Code/test/text2.py
<_sre.SRE_Match object; span=(0, 31), match='name:zhangsan tel:1234567 addr:'>
result1  
result2  beijingshi

Process finished with exit code 0

我们发现,当采用非贪婪匹配时,无法匹配到结果,返回值为空。
因此当遇到需要匹配的值位于字符串结尾的时候,非贪婪匹配将无法匹配到所需要的值,我们需要用贪婪匹配的方式去进行匹配;当需要匹配的值在字符串中间的时候,我们尽量优先使用非贪婪匹配的方式进行匹配。

  1. 修饰符

    在上文中我们讲了两个很重要的两个通用匹配方法,贪婪匹配和非贪婪匹配。但是这两种匹配方式并不是所有字符串都能匹配,因为无论是贪婪(.)还是非贪婪(.?)匹配表达式中都由.(点)来表示任意字符,然而我们在匹配规则中也说明了.(点)可以匹配任意字符,但是换行符除外。因此当我们需要匹配的字符串包含换行符的时候,我么就无法直接使用通用匹配方法了。为了解决这个问题,我们可以用修饰符来修正这个问题。
    常用修饰符:re.S和re.I (大写i)
    re.s : 使.(点)匹配包括换行符在内的所有字符
    re.I : 使匹配对大小写不敏感
    使用时的写法:
    re.match(正则表达式,待匹配的字符串,re.S)
    re.match(正则表达式,待匹配的字符串,re.I)

  2. search()方法的简单介绍
    search()方法的使用与match()方法的使用一模一样,但是它不同从头开始匹配,可以直接匹配中间的值。
    例:

import  re
data = '''
    name:zhangsan 
    tel:1234567 
    addr:beijingshi
'''
result1 = re.search('t.*?(\d+)', data, re.S)
result2 = re.match('t.*?(\d+)', data, re.S)
print(result1)
print('result1 ',result1.group(1))
print('result2 ',result2)

结果:

/Users/Desktop/Code/test/text2.py
<_sre.SRE_Match object; span=(24, 35), match='tel:1234567'>
result1  1234567
None

Process finished with exit code 0

在上例中,我们用search()方法没有从整个字符串的开头name开始匹配,而是直接从中间tel开始匹配,结果是匹配成功,输出了我们想要的值。但是我们用match()方法这样操作时,发现无法成功匹配,返回了None。match()更适合于用来检测某个字符串是否符合某个正则表达式的规则。

  1. findall()
    findall()方法与search()方法一样,都是通过扫描整个字符串进行匹配。但是search()只返回匹配成功的第一个值,后面的值不会返回;而findall()是返回所有匹配成功的值。

关于Python的正则表达式的基本运用就讲这么多了,希望各位看过后都能对正则表达式有一个比较清晰的了解。若对各位有帮助的话记得帮忙点个赞👍哦~

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值