文章目录
前言
依稀记得刚开始接触正则表达式应该是在《编译原理》这门课程中吧,我们学的时候说是叫正规表达式(简称正规式),他有一个贼拉长、不好理解的一个定义,我在这挂一下:
他这算是一种比较规范的定义了,是从编译原理中文法的角度解释了正则表达式的产生。不理解也没关系,毕竟我们不是要去被这些条条框框的东西,我们只需要知道应该怎么用就行了。
到底什么是正则表达式
简单来说,正则表达式是由一群有特定含义的字符或字符串组成,他含有自己的逻辑规则,这类有规则的字符表达式用来对其他字符的过滤或者说匹配操作。举个例子哈,现在有一个字符串是这样的(我乱敲的):al;hgpHJGOJhgjhfkiuagfiuhjghijhgpiuahghttps://www.baidu.comahoghjohgpkajsyhgu65416546351gfahe87r98q987693(&(&^(&)(&(#@%@%ahgoahg
然后我们想在这一串毫无规律可言的字符串中找到我标黄的那个百度网址。如果是用正则表达式的话应该怎么弄呢?首先前面是字母然后冒号加双斜线,最后是域名加路径。我们可以用下面的正则表达式来匹配:
[a-zA-Z]+://[^\s]*
看起来是乱七八糟的一团,但是里面还是有特定的语法规则的。比如,a-z代表匹配任意的小写字母,\s表示匹配任意的空白字符,*就代表匹配前面的字符任意多个,这一串正则表达式就是上面的匹配url(网址)的组合,通过这个正则表达式可以在任意长度的字符串中找到我们需要的url。是不是很方便呢,我们可以利用规定的正则表达式匹配规则来匹配我们网页中的所有东西,只要他能够以文本的形式展现出来就能够匹配。
下面是正则表达式中一些常用的匹配规则:
看完这些确实头大,不过新手入门用到的正则表达式规则不太多,只需要记住基本的一些规则就可以了。当然正则表达式也不是python独有的,python中有一个re库,利用这个库就可以实现正则表达式的所有功能。下面我来介绍一下re库中的一些常用函数。
re库常用函数介绍
match()
match()函数是re库中的一个常用匹配方法,一般有两个参数,即正则表达式和要匹配的字符串,match()一般是从字符串的起始位置开始匹配,就是从头开始匹配,如果匹配成功就返回匹配成功的结果,不匹配就返回None。例如:
import re
content = 'Hello 123 4567 World_This is a Tegex Demo'
result = re.match('^Hello\s\d\d\d\s\d{4}\s\w{10}', content)
print(result)
print(result.group())
print(result.span())
运行结果如下:
<re.Match object; span=(0, 25), match=‘Hello 123 4567 World_This’>
Hello 123 4567 World_This
(0, 25)
首先,声明了一个字符串content,然后是一个正则表达式,^表示匹配一行字符串的开头,说明我们的正则表达式是从Hello开始匹配,\s表示匹配空格\d匹配数字,然后数字比较多的话可以简写,像四个数字就是\d{4},\w{10}表示匹配10个字母、数字以及下划线。输出结果是一个re.Match对象,证明匹配成功,该对象有两个方法:group()方法输出匹配到的内容,span()方法输出匹配范围,就是匹配到的字符串在原字符串中的位置范围。
目标匹配
match()函数匹配时,我们可以通过()来提取匹配字符串中指定的一部分内容,通过调用group()方法并传入分组索引即可,还是上面那个例子,如果我把正则表达式改成
^Hello\s(\d+)\s(\d+)\sWorld
中间多了两个括号,这个括号的作用就是便于后面输出指定的字符内容,像我用group(1)就会返回123,group(2)就会返回456,如果后面还有括号括起来的内容,依次group(3)、group(4)等等来获取。
通用匹配
上面我们写的正则表达式比较复杂,基本上是一个字符就有一个相应的正则字符去匹配,这样是极不可取的,出于这一点我们的正则表达式中有一个万能匹配可以使用,就是.*(读作点星),其中.(点)可以匹配任意字符(换行符除外),*(星)代表匹配前面的字符无数次,所以.*组合起来就可以匹配任意字符了。同样是开始那个例子,我们来改写一下正则表达式:
import re
content = 'Hello 123 4567 World_This is a Tegex Demo'
result = re.match('^Hello.*Demo$', content)
print(result)
print(result.group())
print(result.span())
运行结果:
<re.Match object; span=(0, 41), match=‘Hello 123 4567 World_This is a Tegex Demo’>
Hello 123 4567 World_This is a Tegex Demo
(0, 41)
我们将中间的部分省略,全部替换成.*,后面记得加结尾字符串喔,不然任意匹配的话是不知道匹配多少个的(虽然默认是全部匹配)。
贪婪与非贪婪匹配
当使用上面的通配符.*时,可能有时候不是我们想要的结果,来看下面的例子: