ERE正则引擎
扩展正则表达式(Extended Regular Expression)在BRE的基础上,进行了功能上的扩充,增加了元字符。
在Linux中,常见的使用ERE正则的程序有grep -E|egrep
,sed -r
,awk
等。
ERE的元字符
和BRE的元字符完全相同,在此之上,新增了元字符。
()
,{}
在BRE正则中需要配合\
使用(\(\)
,\{\}
),在ERE中不再需要转义字符。
增加了+
,?
,|
这三个元字符。
元字符 | 描述 |
---|---|
+ |
代表前面一个字符至少匹配一次,匹配次数无上限,如1+ 匹配1 ,11 ,111 ... |
? |
代表前面一个字符至多匹配一次,如a?b 代表匹配b 或ab |
| | 选择匹配,类似于[pattern] ,代表连接的单词任选其一匹配,通常配合() 使用,如(cat|dog) |
() |
用于分组(后祥),本身不匹配任何字符,将模式进行分组,进行整组匹配或反向引用。如(cat)? 代表cat 这个单词至多出现1次。 |
{} |
限制匹配次数。{m,n} 代表前面的字符至少匹配m次,至多匹配n次。m或n省略代表这个边界不限。如{,1} 等同于? ,{1,} 等同于+ 。{n} 代表匹配n次 |
TIPS:
|
两端不要有空格,(|)
的作用是限制|
连接的范围。
ERE正则的运用
例如匹配date +%F
的时间格式:
date +%F | grep -E '^[0-9]{4}-[01][0-9]-[0-3][0-9]$' # 注意,不要把合法性判断放在这里
这段正则是我在下载腾讯漫画的脚本中应用的, 用于判断用户输入的章节列表格式是否合法,猜猜看,这段这则想要匹配的字符串格式是什么?
^\d+([,-]\d+)*$
同样没有用正则对用户输入的合法性做判断,而是在后面的逻辑代码中才对这些范围做判断。
看看这个正则,用于nginx匹配tomcat的静态资源路径:
^/(static/)?(css|fonts|images|img|js)
TIPS: 在一定复杂度的前提下,正则写的越确切越好,意味着出意外的可能性就越小。
*
和+
的原罪 —— 贪婪匹配
*
和+
在正则引擎中,会尽可能多的匹配满足条件的pattern,此外,还有{}
,?
也满足这个规律。这种规律称为贪婪匹配
(greedy matching)。
比如想对HTML标签进行匹配:
echo 'aa<div>test1</div>bb<div>test2</div>cc' | grep -oE '<div>.+</div>'
<div>test1</div>bb<div>test2</div>
这种结果可能是致命的——并不是本意,可能造成无法预估的BUG。
遗憾的是,BER引擎和ERE引擎诞生较早,并不支持非贪婪匹配(lazy matching)。
后续的正则引擎(如Perl的PCRE
)支持了非贪婪模式。在贪婪模式的后面加上?
即可进入非贪婪模式。
echo 'aa<div>test1</div>bb<div>test2</div>cc' | grep -oP '<div>.+?</div>'
<div>test1</div>
<div>test2</div>
TIPS: 正则不适合处理这种标记性文档,会让正则很复杂,难以维护,也不能很好的处理标签嵌套的问题。 建议使用现成的类库做解析。
猜猜看,对于这个字符串copyright 2003.
,用正则^.*[0-9]+
去匹配,匹配到的是什么结果?
小练习
- 试写出一个正则,匹配
十进制
数字(正负数,整数,小数,科学计数法),并用grep
/sed
验证你的结果。
如:
5
-5
+5
1.111111
-10.5
1.1E5
2.2e-5
- 删除
HTML
页面中全部的HTML标签,只保留纯文本部分,如何实现?用相关命令验证你的正则 (也可以用编程语言实现,暂不考虑复杂的情况,假定每个标签都在单独一行,没有出现跨行标签,比如师傅到首页)