@yanglt7
2018-12-03T10:25:13.000000Z
字数 2473
阅读 628
Python
在正则表达式中,如果直接给出字符,就是精确匹配。
例
'00\d' 可以匹配 '007',但无法匹配 '00A';
'\d\d\d' 可以匹配 '010';
'\w\w\d' 可以匹配 'py3';
. 可以匹配任意字符,所以:
要匹配变长的字符,在正则表达式中,
* | 任意个字符(包括0个) |
---|---|
+ | 至少一个字符 |
? | 0 个或 1 个字符 |
{n} | n个字符 |
{n,} | 至少n个字符 |
{n,m} | n至m个字符 |
[\u4E00-\u9FA5] | 连续出现的汉字,是unicode编码 |
要做更精确地匹配,可以用 [] 表示范围,比如:
[0-9a-zA-Z\_] 可以匹配一个数字、字母或者下划线;
[0-9a-zA-Z\_]+ 可以匹配至少由一个数字、字母或者下划线组成的字符串,比如 'a100','0_Z','Py3000' 等等;
[a-zA-Z\_][0-9a-zA-Z\_]* 可以匹配由字母或下划线开头,后接任意个由一个数字、字母或者下划线组成的字符串,也就是 Python 合法的变量;
[a-zA-Z\_][0-9a-zA-Z\_]{0, 19} 更精确地限制了变量的长度是 1-20 个字符(前面 1 个字符 + 后面最多 19 个字符)。
[0-9] 表示 0-9 任意字符都可,[0-9]{9} 表示区间 0 至 9 出现 9 次;
[^1] 表示任意字符只要不是 1 即可;
[.] 就是 . ,无特殊含义。中括号里的字符都不再有特殊含义;
A|B 可以匹配 A 或 B,所以 (P|p)ython 可以匹配 'Python' 或者 'python'。
^ 表示行的开头,^\d 表示必须以数字开头。^1 代表一行的开头必须是 1。
表示必须以数字结束。1$ 代表一行必须以 1 结尾。
s = 'ABC\-001' # Python的字符串
# 对应的正则表达式字符串变成:
# 'ABC-001'
s = r'ABC-001' # Python的字符串
# 对应的正则表达式字符串不变:
# 'ABC-001'
建议使用 Python 的 r 前缀,就不用考虑转义的问题.
match() 方法判断是否匹配,如果匹配成功,返回一个 Match 对象,否则返回 None。常见的判断方法就是:
>>> import re
>>> re.match(r'^\d{3}\-\d{3,8}$', '010-12345')
<_sre.SRE_Match object; span=(0, 9), match='010-12345'>
>>> re.match(r'^\d{3}\-\d{3,8}$', '010 12345')
>>>
test = '用户输入的字符串'
if re.match(r'正则表达式', test):
print('ok')
else:
print('failed')
用正则表达式来把不规范的输入转化成正确的数组。
>>> 'a b c'.split(' ')
['a', 'b', '', '', '', 'c']
>>> re.split(r'\s+','a b c')
['a', 'b', 'c']
>>> re.split(r'[\s\,]+','a,b, c d')
['a', 'b', 'c', 'd']
>>> re.split(r'[\s\,\;]+','a,b;;c d')
['a', 'b', 'c', 'd']
提取子串。用 () 表示的就是要提取的分组(Group)。比如:
^(\d{3})-(\d{3,8})$ 分别定义了两个组,可以直接从匹配的字符串中提取出区号和本地号码:
>>> m = re.match(r'^(\d{3})-(\d{3,8})$','010-12345')
>>> m
<_sre.SRE_Match object; span=(0, 9), match='010-12345'>
>>> m.group(0)
'010-12345'
>>> m.group(1)
'010'
>>> m.group(2)
'12345'
如果正则表达式中定义了组,就可以在 Match 对象上用group()方法提取出子串来。
注意到 group(0) 永远是原始字符串,group(1)、group(2)…… 表示第 1、2、…… 个子串。
正则匹配默认是贪婪匹配,也就是匹配尽可能多的字符,顺序是从右往左匹配。举例如下,匹配出数字后面的0:
>>> re.match(r'^(\d+)(0*)$','102300').groups()
('102300', '')
由于 \d+ 采用贪婪匹配,直接把后面的 0 全部匹配了,结果 0* 只能匹配空字符串了。
必须让 \d+ 采用非贪婪匹配(也就是尽可能少匹配),顺序是从左往右匹配,才能把后面的 0 匹配出来,加个 ? 就可以让 \d+ 采用非贪婪匹配:
>>> re.match(r'^(\d+?)(0*)$','102300').groups()
('1023', '00')
当我们在 Python 中使用正则表达式时,re 模块内部会干两件事情:
编译正则表达式,如果正则表达式的字符串本身不合法,会报错;
用编译后的正则表达式去匹配字符串。
如果一个正则表达式要重复使用几千次,出于效率的考虑,我们可以预编译该正则表达式,接下来重复使用时就不需要编译这个步骤了,直接匹配:
>>> import re
# 编译:
>>> re_telephone = re.compile(r'^(\d{3})-(\d{3,8})$')
# 使用:
>>> re_telephone.match('010-12345').groups()
('010', '12345')
>>> re_telephone.match('010-8086').groups()
('010', '8086')