Linux-正则表达式
背景
处理文本内容的一大利器就是利用正则表达式,这点在vim、sed、gawk、egrep
命令中都是非常重要的知识点,但是不同语言下的正则表达式引擎不同。Linux下有两种引擎的正则表达式:POSIX基础正则表达式引擎(BRE)
、POSIX拓展正则表达式引擎(ERE)
。其中Sed
命令默认用的BRE
中的一部分,而gawk
命令用的是ERE
,所以Sed
使用的时候会有所限制,而gawk
就没有太多的限制,可以直接使用。
就本文而言,BRE
和ERE
的差别体现在如下标识字符中:?
、+
、{}
、()
,这些字符在gawk
中直接使用,而在sed中就需要借助其它:\
,或者指定参数-r
。
内容
首先看表示字符的元字符:.
,它表示任意一个字符;以及表示字符组的符号:[]
1 | echo "shuai" | sed -n -e '/.i/p' |
然而上面取区间的表述方式对连续区间的取值不是很友好,所以,就有了如下的方式:
1 | 用-连接的两个字符,被[]包裹:表示取这两个字符及其之间的所有字符 |
如果像排除某些字符,则可以借助:^
1 | 字符组开头加^表示不取字符组中的内容 |
然后是文本流的开头和结尾的方式:^
、$
1 | ^:匹配一行的开头 |
接着就是字符数目的标识:*
、?
、+
、{}
1 | *:表示*前的字符/分组重复0到无数次 |
还有就是分组的标识:()
,以及管道命令:|
表示或:
1 | ():将部分正则表达式表示为一个整体 |
上面这些特殊字符如何被当作常规字符用在正则匹配中呢?这要看情况而定,对于{}
、()
、+
、?
字符如果当字符匹配,则直接用即可,反而是在正则中需要加\
来标识它们的特殊用处
1 | 匹配字符 |
对于.
、*
、[]
、^
、$
、|
、\
,如果当字符匹配则需要借助\
,而在正则中做特殊标识则直接使用即可。
1 | 匹配字符 |
BRE
正则中的一大特点是其还提供了特殊的字符组,这个就比较重要了,如下:
字符组 | 含义 | 例子 |
---|---|---|
[[:alpha:]] | 匹配任意字母字符,无论大小写,不匹配标点符号 | sed -n -e "/[[:alpha:]]/p" file |
[[:alnum:]] | 匹配任意字母字符0 |
sed -n -e "/[[:alnum:]]/p" file |
[[:blank:]] | 匹配空格或制表符 | sed -n -e "/[[:blank:]]/p" file |
[[:digit:]] | 匹配0~9之间的数字 | sed -n -e "/[[:digit:]]/p" file |
[[:lower:]] | 匹配小写字符a~z | sed -n -e "/[[:lower:]]/p" file |
[[:print:]] | 匹配任意可打印字符 | sed -n -e "/[[:print:]]/p" file |
[[:punct:]] | 匹配标点符号 | sed -n -e "/[[:punct:]]/p" file |
[[:space:]] | 匹配任何空白字符:空格、制表符、CR、FF、VT、NL | sed -n -e "/[[:space:]]/p" file |
[[:upper:]] | 匹配大写字符:A~Z | sed -n -e "/[[:upper:]]/p" file |
注意之处:[[:alpha:]]之间没有任何的空格
,其次[[:alpha:]]
和[[:alnum:]]
没看出差别。
最后的最后,有一点需要着重说明,对于gawk
,如果需要匹配{n,m}
这种格式的次数时,就一定要指定参数:--re-interval
,否则它就认不得:
1 | echo bt | gawk --re-interval '/b{1}t/{print $1}' |