正则表达式
关于正则表达式的基础知识,推荐正则表达式30分钟入门教程。
以下仅对某些特性做些总结:(红色字体表示正则表达式;黑色字体标源字符串;下划线部分表示匹配;如果有连续的多个匹配用绿色加下划线表示)
1 贪婪模式(默认)
当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。
(?:<(w+)>).*(</1>)
<b><b>hello</b></b>
在前后两个括号里的内容可以匹配的前提下,‘.*’会尽可能多的匹配,所以上面的源字符串整体会被匹配到。
加上断言可以只匹配外层标签内的内容,通过这种方式迭代可以取出标签内的文本:
(?<=<(w+)>).*(?=</1>)
<b><b>hello</b></b>
2 懒惰模式
在表示重复的限定符后面加‘?’可以切换到懒惰模式,即在可以匹配的情况下尽可能少的匹配。
- *? 零个或者更多
- +? 一个或者更多
- ?? 零或者一
- {n,m}? 至少n个,最多m个
- {n,} 至少n个
示例:
a.*b
aabab
3 优先级
如果按照懒惰模式的定义,懒惰模式部分的示例应该匹配到两个‘ab’。但是正则中有个规则比懒惰/贪婪规则的优先级更高:最先开始的匹配拥有最高的优先权——The match that begins earliest wins。
用python代码解释下:
s = 'aabab'
ret = []
start = None
for index, char in enumerate(s):
if start is None:
if char == 'a':
start = index
else:
if char == 'b':
ret.append(s[start:index+1])
start = None
print(ret)
4 或
和python中的逻辑或‘or’相同,正则表达式中的或也是短路操作,只要匹配到就会返回,忽略后面的选项。
示例:匹配0-255之间的任意数字(可以有前导0):
[01]?dd?|2[0-4]d|25[0-5]
1
01
187
249
256
# 匹配到的所有数字:1、01、187、24、9、25、6
这个正则表达式有三个分支,匹配的数字范围依次是:0-199, 200-249, 250-255。第一个条件其实可以匹配任意数字,因为任意大于200的数字都可以拆分成一位数和两位数的组合。
可以交换下选项的位置,改进版:
2[0-4]d|25[0-5]|[01]?dd?
1
01
187
249
256
当然上面的版本也还是不满足需求,我们可以通过添加边界条件来控制,合适的边界条件会消除短路的影响。这里只是为了说明‘|’的短路规则。
5 单行模式和多行模式
正则表达式中几个元字符的含义:
- . 除换行符(' ')以外的任意字符
- ^ 字符串的开始
- $ 匹配字符串的结束
单行模式:. 可以匹配任意字符,包括换行符(' ')
多行模式:
- ^ 匹配字符串开始以及' '之后的位置
- $ 匹配字符串结束以及' '之前的位置
单行模式和多行模式可可以同时启用,它们改变的是不同元字符的行为。
参考:
[1] http://deerchao.net/tutorials/regex/regex.htm 正则表达式30分钟入门教程