re
\d | 数字,相当于[0-9] |
\D | 非数字字符,相当于 [^0-9] |
\s | 空白字符,相当于[\t\r\n\f\v] |
\S | 非空白字符 |
\w | 字母或数字,相当于 [0-9a-zA-z] |
\W | 非字母或数字 |
. | 任意字符 |
| | 或 |
^ | 非, 或者开始位置标记 |
$ | 结束位置标记 |
\b | 单词边界 |
\B | 非单词边界 |
重复 | |
* | 0或任意个字符。添加 ?后缀避免贪婪匹配 |
? | 0或一个字符 |
+ | 1或多个字符 |
{n} | n个字符 |
{n,} | 最少n个字符 |
{,m} | 最多m个字符 |
{n,m} | n到mge字符 |
编译 | 可以直接在表达式前部加 "(?iLmsux)" 标志 |
s | 单行 |
i | 忽略大小写 |
m | 多行 |
x | 忽略多余的空白字符 |
u | Unicode |
正则函数
re 有几个重要的函数:
- match(): 匹配字符串开始位置
- search(): 扫描字符串,找到第一个位置
- findall(): 找到全部匹配,以列表返回
- finditer(): 找到全部匹配,以迭代器返回
match 和 search 仅匹配一次,匹配不到返回 None。
>>> import re >>> s = '12abc345ab' >>> m = re.match(r'\d+', s) >>> m.group() '12' >>> m.span() (0, 2) >>> re.match(r'\d{3,}', s) # 开始位置有两个数字,不符合,返回None >>> m = re.match(r'\d{3,}', s) >>> m is None True
>>> s = '12abc345ab' >>> m = re.search(r'\d{3,}', s) >>> m.group();m.span() '345' (5, 8) >>> m = re.search(r'\d+', s) >>> m.group();m.span() '12' (0, 2)
findall 返回列表,match,search返回MatchObject
>>> re.findall(r'\d+', s) ['12', '345']
finditer 返回迭代器
>>> match_iter = re.finditer(r'\d+', s) >>> match_iter <callable_iterator object at 0x7f6cf5e0bcf8> >>> for m in match_iter: ... print(m.group()) ... 12 345
MatchObject
- group(): 返回匹配的完整字符串
- start(): 匹配的开始位置
- end(): 匹配的结束位置
- span(): 包含起始,结束位置的元组
- groups(): 返回分组信息
- groupdict(): 返回命名的分组信息
>>> m = re.match(r'(\d+)(?P<str>[abc]+)', s) # ?P 命名分组 >>> m.group() '12abc' >>> m.groups() ('12', 'abc') >>> m.groupdict() # 命名的分组 {'str': 'abc'}
start()、end() 和 span() 同样能接收分组序号。和 group() 一样,序号 0 表示示整体匹配结果
>>> s = '12abc345ab' >>> m = re.match(r'(\d+)(?P<str>[abc]+)', s) >>> m.start(0); m.end(0) 0 5 >>> m.start(2); m.end(2) 2 5 >>> m.span() (0, 5) >>> m.span(2) # 分组2的起始位置,结束位置 (2, 5)
编译标志
可以使用re.l , re.M等参数,也可以直接在表达式中添加(?iLmsux)标志
- s: 单行,"." 匹配包括换行符在内的所有字符
- i: 忽略大小写
- L: 让"\w" 能够匹配当地字符,对中文支持不好
- m: 多行
- x:忽略多余的空白字符,让表达式更易阅读
- u:Unicode
>>> re.findall(r'[a-z]+','%123Abc%45xyz&')
['bc', 'xyz']
>>> re.findall(r'[a-z]+','%123Abc%45xyz&', re.I)
['Abc', 'xyz']
>>> re.findall(r'(?i)[a-z]+', '%123Abc%45xyz&')
['Abc', 'xyz']
>>>
>>> parttern = r'(\d+)([a-z]+)'
>>> re.findall(parttern, '123Abc%45xyz&', re.I|re.S|re.X)
[('123', 'Abc'), ('45', 'xyz')]
>>>
组操作
命名组:(?P<name>...)
for m in re.finditer(r'(?P<number>\d+)(?P<letter>)[a-z]+', '%123Abc%45xyz&', re.I): print(m.groupdict())
# {'number': '123', 'letter': ''} # {'number': '45', 'letter': ''}
无捕获组:(?....), 作为匹配条件,但不返回
for m in re.finditer(r'(?:\d+)([a-z]+)', '%123Abc%45xyz&', re.I): print(m.groups()) # ('Abc',) # ('xyz',)
修改
split: 用parttern 做分割符切割字符串, 如果用 "(parttern)", 那么分隔符也会返回
>>> re.split(r'\W', 'abc,123,x')
['abc', '123', 'x']
>>> re.split(r'(\W)', 'abc,123,x')
['abc', ',', '123', ',', 'x']
sub: 替换子串。可指定替换次数。
>>> re.sub(r'[a-z]+', '*', 'abc,123,x',1)
'*,123,x'
subn: 返回(新字符串, 替换次数)
>>> re.subn(r'[a-z]+', '*', 'abc,123,x',1)
('*,123,x', 1)
将替换字符串改成函数
>>> def repl(m):
... print(m.group())
... return '*'
...
>>> re.sub(r'[a-z]', repl, 'abc,123,x')
a
b
c
x
'***,123,*'