正则表达式的语法
定义
行定位符
行定位符主要用于描述字符串的边界,^
表示行的开始 $
表示行的结束。
例如:
^tm
上面这个表达式意思就是匹配**以tm开头的字符串**。<br />可以匹配到`tm tomorrow morning`这个字符串。<br />再例如:
tm$
上面的表达式的意思就是匹配**以tm结尾的字符串**。<br />可以匹配到`tomorrow morning tm`这个字符串。
上面两种就是匹配开头和结尾,如果想匹配任意位置的:
tm
或者只匹配`tm`
^tm$
元字符
下面是常用元字符的表。
实例 | 描述 |
---|---|
. | 匹配除 “\n” 之外的任何单个字符。要匹配包括 ‘\n’ 在内的任何字符,请使用象 ‘[.\n]’ 的模式。 |
\d | 匹配一个数字字符。等价于 [0-9]。 |
\D | 匹配一个非数字字符。等价于 [^0-9]。 |
\s | 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 |
\S | 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 |
\w | 匹配包括下划线的任何单词字符。等价于’[A-Za-z0-9_]’。 |
\W | 匹配任何非单词字符。等价于 ‘[^A-Za-z0-9_]’。 |
举个例子:匹配`mr`开头的单词。
\bmr\w*\b
首先两个`\b`分别表示了需要匹配单词的开头和结尾,是一个**标识符号**。<br />其中`mr`就是`mr`,没有特殊含义。<br />`\w`从表中可以看出是用来匹配**包括下划线的任何单词字符。**<br />加了一个`*`表示匹配的**长度是任意的**。
所以该表达式可以匹配:mrsoft
、mrbook
、mr1234
等。
限定符
为了简化书写,可以使用限定符来表达需要匹配的数量。
实例 | 描述 |
---|---|
? | 匹配前面的字符零次或者一次。 |
+ | 匹配前面的字符一次或者多次。 |
* | 匹配前面的字符零次或者多次。 |
{n} | 匹配前面的字符n次。 |
{n,} | 匹配前面的字符至少n次(包括n次) |
{n,m} | 匹配前面的字符最少n次,最多m次。 |
举个例子:
employe{0,2}
上面的表达式可以匹配`employ``employe``employee`这个三个字符串。
字符类
如果想要在一个数组范围内寻找需要匹配的字符,就可以使用字符类,只需要再方括号**[]**
中列出需要匹配的字符即可。
例如:匹配元音字母:
[aeiou]
再例如匹配任意一个字母。
[a-zA-Z]
这个就表示匹配所有a到z和A-Z的字母。
排除字符
^
在之前是表示行的开始,但是在[]
中表示的就是排除。
例如:匹配一个不是字母的字符。
[^a-zA-Z]
选择字符
选择字符:**|**
,可以理解成为“或”。
举个例子:匹配一个号码是否是身份证号?
身份证号码规则为:长度为15位或者18位。如果为15位则应该全都是数字。如果是18位,则前17位是数字,最后一位是数字或者X或者x。
正则表达式如下:
(^\d{15}$)|(^\d{17})(\d|X|x)$
(^\d{15}$)
就表示十五位数字。(^\d{17})(\d|X|x)$
就表示前面开头17位是数字,最后一位是数字或者X或者x。
转义字符串
例如,我们需要匹配类似127.0.0.1
这种类型的字符串的时候,.
在前文中提到是表示除了换行符意外的任意字符,所以表示.
需要用转义字符串。
[1-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}
在Python中使用正则表达式语法
模式字符串
在Python中使用正则表达式的时候,是将其作为模式字符串使用的。
比如:匹配任意非字母
字符
正则表达式如下:
[^a-zA-Z]
在Python中需要写成:
'[^a-zA-Z]'
也就是需要开头和结尾都加`'`,也就是**定界符**<br />如果遇到特殊符号需要进行**转义**<br />例如:匹配以m为开头的单词
\bm\w*\b
在Python需要写成:
'\\bm\\w*\\b'
这样就比较麻烦,所以我们一般都直接在前面加一个`r`或者`R`即可。
r'\bm\w*\b'
表达式修饰符
修饰符 | 描述 |
---|---|
re.I | 使匹配对大小写不敏感 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ |
re.S | 使 . 匹配包括换行在内的所有字符 |
re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
使用re模块实现正则表达式操作
字符串匹配
re.match()
语法:
re.match(pattern, string, flags=0)
参数说明:
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
string | 要匹配的字符串。 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 |
`macth()`方法是从**字符串的开头开始匹配**,如果在该字符串匹配到了,则返回一个匹配的对象,如果没有则返回`None`。
注意这里:如果开头的字符串不符合匹配条件,则不会往下进行匹配。
举个例子:
# 注意这里需要导入re
import re
print(re.match('w\d+', 'www.runoob.com'))
print(re.match('w\w*', 'www.runoob.com'))
print(re.match('com', 'www.runoob.com'))
# 这里com虽然在结尾有,但是开头就已经不符合匹配规则了,所以匹配不到。
看一下代码的运行结果
可以看到这里有个span
,表示的是匹配到字符串开头到结尾索引的位置。
import re
print(re.match('www', 'www.runoob.com').span()) # 在起始位置匹配
print(re.match('com', 'www.runoob.com')) # 不在起始位置匹配
# 运行结果为
# (0, 3)
# None
同时可以使用`group()`方法来获取匹配到的对象。<br />这里再举一个例子:
#!/usr/bin/python
import re
line = "Cats are smarter than dogs"
matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)
if matchObj:
print "matchObj.group() : ", matchObj.group()
print "matchObj.group(1) : ", matchObj.group(1)
print "matchObj.group(2) : ", matchObj.group(2)
else:
print "No match!!"
执行结果如下:
matchObj.group() : Cats are smarter than dogs
matchObj.group(1) : Cats
matchObj.group(2) : smarter
这里的`.group()`返回的就是匹配到的字符串。<br />后面两个是`(.*)`和`(.*?)`中匹配到的字符串,也就是括号中的字符串。
re.search()
语法:
re.search(pattern, string, flags=0)
参数说明同上。research
方法和match
方法的区别在于:
research
方法是匹配整个字符串的,直到找到一个匹配的。match
方法是从头开始匹配,如果开头不符合就返回None。
举例对比一下:
import re
print(re.match('www', 'www.runoob.com').span()) # 在起始位置匹配
print(re.match('com', 'www.runoob.com')) # 不在起始位置匹配
# 运行结果为
# (0, 3)
# None
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import re
print(re.search('www', 'www.runoob.com').span()) # 在起始位置匹配
print(re.search('com', 'www.runoob.com').span()) # 不在起始位置匹配
# 执行结果为
# (0, 3)
# (11, 14)
re.findall()
语法:
re.findall(pattern , string , pos,endpos)
参数说明:
- string : 待匹配的字符串。
- pattern :正则表达式。
- pos : 可选参数,指定字符串的起始位置,默认为 0。
- endpos : 可选参数,指定字符串的结束位置,默认为字符串的长度。
举个例子:
# -*- coding:UTF8 -*-
import re
pattern = re.compile(r'\d+') # 查找数字
result1 = pattern.findall('runoob 123 google 456')
result2 = pattern.findall('run88oob123google456', 0, 10)
print(result1)
print(result2)
# ['123', '456']
# ['88', '12']
字符串替换
re.sub()
语法:
re.sub(pattern, repl, string, count=0, flags=0)
参数说明:
- pattern : 正则中的模式字符串。
- repl : 替换的字符串,也可为一个函数。
- string : 要被查找替换的原始字符串。
- count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
举个例子:
import re
phone = "2004-959-559 # 这是一个国外电话号码"
# 删除字符串中的 Python注释
num = re.sub(r'#.*$', "", phone)
print ("电话号码是: ", num)
# 删除非数字(-)的字符串
num = re.sub(r'-', "", num)
print ("电话号码是 : ", num)
# 电话号码是: 2004-959-559
# 电话号码是 : 2004959559
上面的还可以写成
import re
phone = "2004-959-559 # 这是一个国外电话号码"
# 删除字符串中的 Python注释
num = re.sub(r'#.*$', "", phone)
print ("电话号码是: ", num)
# 删除非数字(-)的字符串
num = re.sub(r'\D', "", phone)
print ("电话号码是 : ", num)
# 电话号码是: 2004-959-559
# 电话号码是 : 2004959559
如果是需要传入函数的话:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import re
# 将匹配的数字乘以 2
def double(matched):
value = int(matched.group('value'))
return str(value * 2)
s = 'A23G4HFD567'
print(re.sub('(?P<value>\d+)', double, s))
这里的
?P
表示命名,\d+
表示一个或者多个数字组成的数,例如这里的23``4``567
,<value>
就是把后面的数字命名为value
,(?P<value>\d+)
用括号包裹表示在group中,所以只需要用value
就可以从group中获得匹配到的数字。
re.compile()
compile()函数主要用于编译正则表达式,生成一个正则表达式对象。
语法:
re.compile(pattern[, flags])
参数:
- pattern : 一个字符串形式的正则表达式
- flags : 可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为:
用法很简单:
import re
pattern = re.compile(r'([a-z]+) ([a-z]+)', re.I)
# re.I 表示忽略大小写
# 注意中间存在一个空格
m = pattern.match('Hello World Wide Web')
print (m) # 匹配成功,返回一个 Match 对象
# <re.Match object; span=(0, 11), match='Hello World'>
字符串分割
re.spilt()
语法:
re.split(pattern, string, maxsplit=0, flags=0)
参数说明:
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
string | 要匹配的字符串。 |
maxsplit | 分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 |
同样比较简单,举个例子就懂了
import re
print(re.split(',', 'runoob,runoob,runoob.'))
print(re.split('a*', 'hello world'))
# ['runoob', 'runoob', 'runoob.']
# ['', 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '']
注意第二个返回结果的开头和结尾。