1 前言
你一定不会陌生【\d】、【[a-z]+】之类的表达式,前者匹配一个数字字符,后者匹配一个以上的小写英文字母。但是如果你用过 vi、grep、awk、sed 之类 Linux/Unix 下的工具或许会发现,这些工具虽然支持正则表达式,语法却很不一样,照通常习惯的办法写的【\d】【a-z]+】之类的正则表达式,往往不是无法识别就是匹配错误。而且,这些工具自身之间也存在差异,同样的结构,有时需要转义有时不需要转义。为什么呢,得从标准说起: |
---|
- Unix/Linu下的工具大多采用POSIX规范,POSIX规范源于PERL,POSIX又分为两种流派:
- BRE(基本正则表达式): grep、vi、sed都属于这一流派,语法比较奇怪。
- ERE(扩展正则表达式): egrep(和grep -E语法一致)、awk属于这一流派。
@note: BRE名为基本,ERE为扩展,但是语法几乎不兼容,分属两大流派。
- PCRE(Perl Compatible Regular Expressions)是一个Perl库,包括 perl兼容的正则表达式库。这些在执行正规表达式模式匹配时用与Perl 5同样的语法和语义是很有用的。
- grep -P表示使用PCRE语法。建议使用PCRE规范的正则,但是也会引起性能的下降。
2 正则语法
2.1 正则相关概念
- 元字符: 正则表达式语言由两种基本字符类型组成:原义(正常)文本字符和元字符。元字符使正则表达式具有处理能力。所谓元字符就是指那些在正则表达式中具有特殊意义的专用字符,可以用来规定其前导字符(即位于元字符前面的字符)在目标对象中的出现模式。
2.2 正则语法
表1 常用正则语法/元字符
功能 | BRE | ERE | PCRE | 备注 |
---|---|---|---|---|
匹配任意字符 | . | . | . | |
字符集匹配 | [] | [] | [] | |
字符集否定匹配 | [^] | [^] | [^] | |
开始位置 | ^ | ^ | ^ | |
结束位置 | $ | $ | $ | |
子表达式(匹配 pattern) | \(pattern\) | (pattern) | (pattern) | |
匹配 pattern 但不获取匹配结果 | 不支持 | 不支持 | (?:pattern) | |
匹配x或y | 不支持 | x|y | x|y | |
子表达式向前引用 | \n(n表示数字) | $n | ||
至少m次,至多n次匹配 | \{m,n\} | {m,n} | {m,n} | |
至少m次匹配 | \{m,\} | {m,} | {m,} | |
至多n次匹配 | \{,n\} | {,n} | {,n} | |
任意次匹配 | * | * | * | |
0次或1次匹配 | 不支持 | ? | ? | |
所有空格字符 | | | \s | |
非空格字符 | [^[:space:]] | \S [^[:space:]] | \S | |
十进制字符数字 | | | \d | ...... |
非十进制数字 | | | \D | |
十六进制数字 | | | \xn | n表示十六进制数字 |
十六进制数字 | | | \Xn | |
匹配字母、数字、下划线 | | | \w | |
非字母、数字、下划线 | | | \W | |
Unicode 字符 | 不支持 | 不支持 | \un | \u00A9 匹配版权符号 (?) |
单词边界 | 不支持 | 不支持 | \b | |
非单词边界 | 不支持 | 不支持 | \B | |
单词开始位置 | 不支持 | 不支持 | | |
单词结束位置 | 不支持 | 不支持 | | |
换行符 | \n | |||
制表符 | \t | |||
回车符 | \r |
表2 正则断言
功能 | BRE | ERE | PCRE | 备注 |
---|---|---|---|---|
先行断言(零宽度正预测先行断言) | 不支持 | 不支持 | (?=pattern) | 正向肯定预查(look ahead positive assert),在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,"Windows(?=95|98|NT|2000)"能匹配"Windows2000"中的"Windows",但不能匹配"Windows3.1"中的"Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。 |
后发断言(零宽度正回顾后发断言) | 不支持 | 不支持 | (?<=pattern) | 反向(look behind)肯定预查,与正向肯定预查类似,只是方向相反。例如,"(?<=95|98|NT|2000)Windows "能匹配"2000Windows "中的"Windows ",但不能匹配"3.1Windows "中的"Windows "。 |
负向零宽先行断言 | 不支持 | 不支持 | (?!pattern) | 正向否定预查(negative assert),在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如"Windows(?!95|98|NT|2000)"能匹配"Windows3.1"中的"Windows",但不能匹配"Windows2000"中的"Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。 |
负向零宽后发断言 | 不支持 | 不支持 | (?<!pattern) | 反向否定预查,与正向否定预查类似,只是方向相反。例如"(?<!95|98|NT|2000)Windows "能匹配"3.1Windows "中的"Windows ",但不能匹配"2000Windows "中的"Windows "。 |
表3 扩展正则语法/元字符
功能 | BRE | ERE | PCRE | 备注 |
字母和数字 | | | | [^[:alnum:]]表示非字母数字 |
字母 | | [:alpha:] | [:alpha:] | ... |
小写字母 | | [:lower:] | [:lower:] | ... |
大写字母 | | | | ... |
空格和制表符 | | | | ... |
不可打印的控制 字符 | | | \cx | x 的值必须为 A-Z 或 a-z 之一 |
可打印的空白字符 | | | | .. |
可打印字符 | | | [:print:] | |
标点符号 | | | |
Openresty正则开发:
https://blog.csdn.net/weixin_40783338/article/details/107424342
引用三方链接
- PCRE英文文档: http://www.pcre.org/
- PCRE正则表达式标准学习文档: https://www.runoob.com/regexp/regexp-tutorial.html
- Openresty API: https://github.com/openresty/lua-nginx-module
- Openresty/lua正则表达式: https://www.jianshu.com/p/89f86c347932
- BRE和ERE差异: http://blog.chinaunix.net/uid-23045379-id-2562051.html
- Openresty正则使用: http://www.hangdaowangluo.com/archives/2731
- lua原生正则: https://www.runoob.com/lua/lua-strings.html