正则表达式

正则表达式

正则表达式(英语:Regular Expression,在代码中常简写为regex、regexp或RE),又称正规表示式、正规表示法、正规表达式、规则表达式、常规表示法,是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些匹配某个模式的文本。

match()

这里首先介绍第一个常用的匹配方法— match(),向它传入要匹配的字符串以及正则表达式,就可以检测这个正则表达式是否匹配字符串。match()方法会尝试从字符串的起始位置匹配正则表达式,如果匹配,就返回匹配成功的结果;如果不匹配,就返回None。
示例如下:

import re

content = "Hello 123 4567 World_This is a Regex Demo"
print(len(content))
result = re.match("^Hello.*Demo$",content)
print(result)
print(result.group())
print(result.span())

在 match()方法中,第一个参数传入了正则表达式,第二个参数传入了要匹配的字符串。打印输出结果,可以看到结果是 SRE Match对象,这证明成功匹配。该对象有两个方法: group()方法可以输出匹配到的内容,结果是He1lo1234567 World this,这恰好是正则表达式规则所匹配的内容;span()方法可以输出匹配的范围,结果是(0,25),这就是匹配到的结果字符串在原字符串中的位置范围

匹配目标

刚才我们用 match()方法可以得到匹配到的字符串内容,但是如果想从字符串中提取一部分内容,
该怎么办呢?就像最前面的实例一样,从一段文本中提取出邮件或电话号码等内容。
这里可以使用()括号将想提取的子字符串括起来。()实际上标记了一个子表达式的开始和结束位
置,被标记的每个子表达式会依次对应每一个分组,调用 group()方法传入分组的索引即可获取提取
的结果。
示例如下:

content = "Hello 1234567 World_This is a Regex Demo"
result = re.match("^Hello\s(\d+)\s\w{10}",content)
print(result)
print(result.group())
print(result.group(1))
print(result.span())

可以看到,我们成功得到了1234567。这里用的是 group(1),它与 group()有所不同,后者会输出完整的匹配结果,而前者会输出第一个被()包围的匹配结果。假如正则表达式后面还有()包括的内容,那么可以依次用 group(2)、 group(3)等来获取。

通用匹配

刚才我们写的正则表达式其实比较复杂,出现空白字符我们就写\s匹配,出现数字我们就用\d匹配,这样的工作量非常大。其实完全没必要这么做,因为还有一个万能匹配可以用,那就是*(点星)。其中.(点)可以匹配任意字符(除换行符),*(星)代表匹配前面的字符无限次,所以它们组合在一起就可以匹配任意字符了。有了它,我们就不用挨个字符地匹配了

import re

content = "Hello 1234567 World_This is a Regex Demo"
print(len(content))
result = re.match("^He.*(\d+).*Demo$",content)
print(result)
print(result.group())
print(result.group(1))
print(result.span())

贪婪与非贪婪

在贪婪匹配下,* 会匹配尽可能多的字符。正则表达式中*后面是\d+,也就是至少一个数字,并没有指定具体多少个数字,因此,.* 就尽可能匹配多的字符但这很明显会给我们带来很大的不便。有时候,匹配结果会莫名其妙少了一部分内容。其实,这里只需要使用非贪婪匹配就好了。非贪婪匹配的写法是.*?,多了一个?

import re

content = "Hello 1234567 World_This is a Regex Demo"
print(len(content))
result = re.match("^He.*?(\d+).*Demo$",content)
print(result)
print(result.group())
print(result.group(1))
print(result.span())

在做匹配的时候,字符串中间尽量使用非贪婪匹配,也就是用.?来代替.,以免出现匹配结果缺失的情况。

修饰符

正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。

import re

content = '''Hello 1234567 World_This is a 
    Regex Demo'''
print(len(content))
result = re.match("^He.*?(\d+).*Demo$",content,re.S)
print(result)
print(result.group(1))

转义匹配

我们知道正则表达式定义了许多匹配模式,如匹配除换行符以外的任意字符,但是如果目标字符串里面就包含,那该怎么办呢?这里就需要用到转义匹配了,当遇到用于正则匹配模式的特殊字符时,在前面加反斜线转义一下即可。
示例如下

import re

content = "(谷歌)www.google.com"
result = re.match("\(谷歌\)www\.google\.com",content)
print(result.group())

search()

因为 match()方法在使用时需要考虑到开头的内容,这在做匹配时并不方便。它更适合用来检测某个字符串是否符合某个正则表达式的规则。
这里就有另外一个方法 search(),它在匹配时会扫描整个字符串,然后返回第一个成功匹配的结果。也就是说,正则表达式可以是字符串的一部分,在匹配时, search()方法会依次扫描字符串,直到找到第一个符合规则的字符串,然后返回匹配内容,如果搜索完了还没有找到,就返回None。
为了匹配方便,我们尽可能使用search()方法

import re

content = '''<p class="comment">我们终此一生都在寻找那个最真实的自己<img class="face-image" title="悲伤" src="//s1.xmcdn.com/css/img/face/d_beishang.gif"></p>
<p class="comment-body">大半夜,哭了,温暖了所有人,什么都没有得到</p>
<p class="comment">想做个冷淡的人,前提是你得有资本够强大</p>
'''
result = re.search('<p.*body">(.*?)</p>',content,re.S)
print(result.group(1))

findall()

前面我们介绍了 search()方法的用法,它可以返回匹配正则表达式的第一个内容,但是如果想要获取匹配正则表达式的所有内容,那该怎么办呢?这时就要借助 finda11(方法了。该方法会搜索整个字符串,然后返回匹配正则表达式的所有内容

import re

content = '''<p class="comment">我们终此一生都在寻找那个最真实的自己<img class="face-image" title="悲伤" src="//s1.xmcdn.com/css/img/face/d_beishang.gif"></p>
<p class="comment">大半夜,哭了,温暖了所有人,什么都没有得到</p>
<p class="comment">想做个冷淡的人,前提是你得有资本够强大</p>
'''
results = re.findall('<p.*?>(.*?)</p>',content,re.S)
for result in results:
    print(result)

如果只是获取第一个内容,可以用search()方法,当需要提取多个内容时,可以用findall()方法

sub()

#除了使用正则表达式提取信息外,有时候还需要借助它来修改文本。比如,想要把一串文本中的所有数字都去掉,如果只用字符串的 replace()方法,那就太烦琐了,这时可以借助sub()方法。

import re

content = "gsfd3df13132fgdfgdf1d3fg"
result = re.sub('\d+','',content)
print(result)

这里只需要给第一个参数传入\d+来匹配所有的数字,第二个参数为替换成的字符串(如果去掉该参数的话,可以赋值为空),第三个参数是原字符串

compile()

前面所讲的方法都是用来处理字符串的方法,最后再介绍一下 compile()方法,这个方法可以将正则字符串编译成正则表达式对象,以便在后面的匹配中复用。示例代码如下:

import re

content1 = "2019-2-11 17:00"
content2 = "2019-2-12 17:29"
content3 = "2019-2-14 17:42"

pattern = re.compile('\d{2}:\d{2}')
result1 = re.sub(pattern,'',content1)
result2 = re.sub(pattern,'',content2)
result3 = re.sub(pattern,'',content3)
print(result1,result2,result3)

另外, compile()还可以传入修饰符,例如re.S等修饰符,这样在 search()、 findall1()等方法中就不需要额外传了。所以, compile()方法可以说是给正则表达式做了一层封装,以便我们更好地复用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值