正则表达式是一种用来匹配字符串的。它的设计思想是用一种描述性的语言来给字符串定义一个规则,凡符合规则的字符串,就认为它“匹配”了,否则,该字符串就是不合法的。在正则表达式中,如果直接给出字符,就是精确匹配。
正则表达式
Python正则表达式
基础
【匹配数字和字母】:\d
可以匹配一个数字,\w
可以匹配一个字母或数字
00\d
可以匹配007
,但是无法匹配00A
\d\d\d
可以匹配010
\w\w\d
可以匹配py3
【匹配任意字符】:.
py.
可以匹配pyf
、pyu
、py9
等等。
【匹配变长的字符】:在正则表达式中,用*
表示任意个字符(包括0个),用+
表示至少一个字符,用?
示0个或1个字符,用{n}
表示n个字符,用{n,m}
表示n-m个字符
\d{4}\s+\d{3,8}
1 、\d{4}
表示匹配4个数字,例如'0851'
;
2、\s
可以匹配一个空格(也包括Tab等空白符),所以\s+
表示至少有一个空格,例如匹配' '
,' '
等;
3、\d{3,8}
表示3-8
个数字,例如'1234567'
。
特殊字符需要用\
转义:-
字符,转义\-
进阶
精确地匹配,可以用[]
表示范围
[0-9a-zA-z\_]
:匹配一个数字、字母或者下划线[0-9a-zA-z\_]+
:匹配至少由一个数字、字母或者下划线组成的字符串,如a200
、0_Z
、py1000
等等[a-zA-Z\_][0-9a-zA-Z\_]*
:匹配由字母或下划线开头,后接任意个由一个数字、字母或者下划线组成的字符串[a-zA-Z\_][0-9a-zA-Z\_]{0,19}
:精确地限制了变量的长度是1-20个字符(前面1个字符+后面最多19个字符)
A|B
可以匹配A或B,所以(P|p)ython
可以匹配'Python'
或者'python'
。
^
表示行的开头,^\d
表示必须以数字开头。
$
表示行的结束,\d$
表示必须以数字结束
re模块
在Python中使用正则表达式了。Python提供re
模块,包含所有正则表达式的功能。由于Python的字符串本身也用\
转义,所以要特别注意。
[re.match]
函数语法:re.match(pattern, string, flags=0)
参数 | 描述 |
---|---|
pattern | 匹配的正则表达式 |
string | 要匹配的字符串 |
flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等(正则表达式修饰符 - 可选标志) |
- 正则表达式修饰符 - 可选标志:
正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位OR(|)
它们来指定。如re.I | re.M
被设置成I
和M
标志:
修饰符 | 描述 |
---|---|
re.I | 使匹配对大小写不敏感 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ |
re.S | 使 . 匹配包括换行在内的所有字符 |
re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
import re
num_a = r'^\d{4}\-\d{3,8}$'
# match()方法判断是否匹配,如果匹配成功,返回一个Match对象,否则返回None
print(re.match(num_a, '0853-123345')) # <re.Match object; span=(0, 11), match='0853-123345'>
print(re.match(num_a, '0853 123345')) # None
# 判断方法
re_test = r'^\d{4}\-\d{3,8}$'
if re.match(re_test, '0853-123345'):
print('匹配正确')
else:
print('匹配失败')
[re.search]
函数语法:re.search(pattern, string, flags=0)
print(re.search('www', 'www.python.org').span())
'''
(0,3)
'''
line = 'Cats are smarter than pigs'
sObj = re.search(r'^(.*) are (.*?) .*$', line, re.M | re.I)
if sObj:
print('sObj.group():%s' % sObj.group())
print('sObj.group(1):%s' % sObj.group(1))
print('sObj.group(2):%s' % sObj.group(2))
else:
print('Not found')
sObj.group():Cats are smarter than dogs
sObj.group(1):Cats
sObj.group(2):smarter
re.match
只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None
;而re.search
匹配整个字符串,直到找到一个匹配。
[re.sub]
re.sub
用于替换字符串中的匹配项:re.sub(pattern, repl, string, count=0, flags=0)
- pattern : 正则中的模式字符串。
- repl : 替换的字符串,也可为一个函数。
- string : 要被查找替换的原始字符串。
- count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
phone = '0853-121-211 # 一个电话号码'
# 删除注释
num = re.sub(r'#.*$','',phone)
print(num)
# 删除‘-’字符
num = re.sub(r'\D','',phone)
print(num)
0853-121-211
0853121211
切分字符串
用正则表达式切分字符串比用固定的字符更灵活:
# 切割字符串
str_a = 'a b x'
str_b = 'a,b,c ;f,d'
# 正常的切分代码(无法识别连续的空格)
print(str_a.split(' ')) # ['a', 'b', '', '', '', 'x']
# 正则表达式切分代码
print(re.split(r'\s+', str_a)) # ['a', 'b', 'x']
print(re.split(r'[\s\,\;]+', str_b)) # ['a', 'b', 'c', 'f', 'd']
分组
除了简单地判断是否匹配之外,正则表达式还有提取子串的强大功能。用()
表示的就是要提取的分组(Group):
匹配对象方法 | 描述 |
---|---|
group(num=0) | 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。 |
groups() | 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。 |
# 分组
g_re = r'^(\d{4})-(\d{3,8})$'
m = re.match(g_re, '0853-123456')
print(m)
print(m.group(0))
print(m.group(1))
print(m.group(2))
<re.Match object; span=(0, 11), match='0853-123456'>
0853-123456
0853
123456
group(0)
永远是原始字符串,group(1)
、group(2)
……表示第1、2、……个子串。
贪婪匹配
正则匹配默认是贪婪匹配,也就是匹配尽可能多的字符。
# 贪婪匹配
s_re = r'(\d+)(0*)$'
s = re.match(s_re,'10320000').groups()
print(s)
('10320000', '')
\d+
采用贪婪匹配,直接把后面的0
全部匹配了,结果0*
只能匹配空字符串了,\d+
采用非贪婪匹配(也就是尽可能少匹配),才能把后面的0
匹配出来,加个?
就可以让\d+
采用非贪婪匹配。
# 贪婪匹配
s_re = r'(\d+?)(0*)$'
s = re.match(s_re,'10320000').groups()
print(s)
('1032', '0000')