From 洛谷日报
正则表达式(Regular Expression, 简写为regex)
选择
|:或运算,选择(最低优先级)。
数量限定
+:前面的字符至少出现一次;
?:最多出现一次;
*:出现任意次(包括0次)。
括号
定义范围和优先度。
PCRE表达式
^:匹配输入字符串的开始位置。
$:匹配输入字符串的结束位置。
.:匹配除\r,\n之外任何单个字符。
{n}:匹配确定的n次。
{n,}:至少匹配n次。
{n,m}:最少n次最多m次。
?:非贪心量化:当该字符在任何其他重复修饰符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的(默认为贪婪)。例如,对于字符串"oooo","o+?“将匹配单个"o”,而"o+“将匹配所有"o”。

(?:pattern):难以叙述…例如:industr(?:y|ies)等价于industry|industries。也就是说,如果pattern没匹配上,那么前面的字符也不匹配。
(?=pattern):正向肯定预查。Windows(?=95|98|NT|2000)能匹配Windows2000中的Windows,但不能匹配Windows3.1中的Windows。预查不消耗字符。
(?!pattern):正向否定预查。
(?<=pattern):反向肯定预查。(?<=95|98|NT|2000)Windows能匹配2000Windows中的Windows,但不能匹配3.1Windows中的Windows。
(?<!pattern):反向否定预查。
[xyz]:匹配所包含的任意一个字符。
[^xyz]:匹配任意一个其他字符。
[x-z]:匹配范围内的任意一个字符。([^x-z]反之)
\b:匹配一个单词边界。
\B:匹配一个非单词边界。
\d:匹配一个数字。(\D反之)
\s:匹配一个空白字符。
\w:匹配任何单词字符(即字母、数字、下划线)。
POSIX字符组
[:alnum:]
[:alpha:]
[:ascii:]
[:lower:]
[:upper:]
优先级
| 优先权 | 符号 |
|---|---|
| 最高 | \ |
| 高 | ()、(?:)、(?=)、[] |
| 中 | *、+、?、{n}、{n,}、{n,m} |
| 低 | ^、$、中介字符 |
| 次最低 | 串接,即相邻字符连接在一起 |
| 最低 | | |
Python应用
使用re库。
re.match(r'^\d{3}\-\d{3,8}$', '010-12345'),建议使用r前缀避免考虑Python的转义问题(正则的转义,如\-仍然要考虑)。re.match尝试从起始位置匹配一个模式。
匹配成功返回一个Match对象,否则返回None。
re.search()扫描整个字符串并返回第一个成功的匹配。
findall()返回一个list,内容是所有匹配的子串(str)。
Match对象的方法:
start()返回匹配开始的位置end()span()返回(start(),end())
匹配邮件地址
re.match(r'^\w+(\w+|\.\w+)+@\w+(\w+|\.\w+)+$', addr)
切分字符串
'a b c'.split(' ')无法识别连续的空格。
re.split(r'\s+','a b c')可以。
分组
用()表示要提取的分组。例如^(\d{3})-(\d{3,8})$定义了两个组。使用group()方法取出:
1 | m = re.match(r'^(\d{3})-(\d{3,8})$', '010-12345') |
命名分组
(?P<name>regex),调用:matchobj.group(name)
编译
每次使用正则表达式都需要编译,如果多次使用可以预编译:
1 | import re |
替换
re.sub(pattern,repl,string)
repl是替换后的字符串,也可以是一个函数:这个函数传入的参数为Match对象。
假如文本有个单纯重复了 2 次,利用正则保留一个输出:
1 | import re |