Linux 正则表达式 扩展正则表达式 gawk
什么是正则表达式
正则表达式是我们所定义的模式模板(pattern template),Linux工具用它来过滤文本。Linux工具(比如sed编辑器或gawk程序)能够在处理数据时,使用正则表达式对数据进行模式匹配。如果数据匹配模式,会被接受并进一步处理;如不匹配模式,则会被滤掉。
正则表达式是通过正则表达式引擎(regular expression engine)实现的。Linux有两种流行的正则表达式引擎:
- POSIX基础正则表达式(basic regular expression,BRE)引擎
- POSIX扩展正则表达式(extended regular expression,ERE)引擎
sed编辑器只符合BRE引擎规范的子集,能匹配数字、单词以及按字母排序的字符。
gawk程序用ERE引擎来处理它的正则表达式模式。
gawk程序可以使用大多数扩展正则表达式模式符号,并且能提供一些额外过滤功能,因为如此,gawk程序在处理数据流时通常才比较慢。
1、问号
表明前面的字符可以出现0次或1次,不会匹配多次出现的字符。
$ echo "bt" | gawk '/be?t/{print $0}'
bt
$ echo "bet" | gawk '/be?t/{print $0}'
bet
$ echo "beet" | gawk '/be?t/{print $0}'
$
$ echo "beeet" | gawk '/be?t/{print $0}'
$
可以将问号和字符组一起使用:
$ echo "bt" | gawk '/b[ae]?t/{print $0}'
bt
$ echo "bat" | gawk '/b[ae]?t/{print $0}'
bat
$ echo "bot" | gawk '/b[ae]?t/{print $0}'
$
$ echo "bet" | gawk '/b[ae]?t/{print $0}'
bet
$ echo "baet" | gawk '/b[ae]?t/{print $0}'
$
$ echo "beat" | gawk '/b[ae]?t/{print $0}'
$
$ echo "beet" | gawk '/b[ae?t/{print $0}'
$
如果两个字符都出现,或者其中一个字符出现了2次,模式匹配不成立。
2、加号
加号表明前面的字符可以出现1次或多次,必须至少出现1次。如果该字符没有出现,那么模式就不会匹配。
$ echo "beeet" | gawk '/be+t/{print $0}'
beeet
$ echo "beet" | gawk '/be+t/{print $0}'
beet
$ echo "bet" | gawk '/be+t/{print $0}'
bet
$ echo "bt" | gawk '/be+t/{print $0}'
$
#字符e没有出现,模式匹配就不成立
$ echo "bt" | gawk '/b[ae]+t/{print $0}'
$
$ echo "bat" | gawk '/b[ae]+t/{print $0}'
bat
$ echo "bet" | gawk '/b[ae]+t/{print $0}'
bet
$ echo "beat" | gawk '/b[ae]+t/{print $0}'
beat
$ echo "beet" | gawk '/b[ae]+t/{print $0}'
beet
$ echo "beeat" | gawk '/b[ae]+t/{print $0}'
beeat
$
# 字符组中定义的任一字符出现,文本就会匹配指定模式。
3、花括号
ERE中的花括号允许我们为可重复的正则表达式指定一个上限,这通常称为间隔(interval)。可以用两种格式来指定区间:
- m:正则表达式准确出现m次
- m, n:正则表达式至少出现m次,至多n次。
注意:默认情况下,gawk程序不会识别正则表达式间隔,必须指定gawk程序的--re- interval命令行选项才能识别正则表达式间隔。
echo "bt" | gawk --re-interval '/be{1}t/{print $0}'
# 无输出,指定要出现一次e
echo "bet" | gawk --re-interval '/be{1}t/{print $0}'
# 输出 betecho "beet" | gawk --re-interval '/be{1}t/{print $0}'
# 无输出,指定输出一个e,存在两个e
echo "bt" | gawk --re-interval '/b[ae]{1,2}t/{print $0}'
# 无输出,[ae]中的一个字母至少出现一次,最多出现两次
echo "bat" | gawk --re-interval '/b[ae]{1,2}t/{print $0}'
# 输出bat
echo "bet" | gawk --re-interval '/b[ae]{1,2}t/{print $0}'
# 输出bet
echo "beat" | gawk --re-interval '/b[ae]{1,2}t/{print $0}'
# 输出beat
echo "beet" | gawk --re-interval '/b[ae]{1,2}t/{print $0}'
# 输出beet
echo "beeat" | gawk --re-interval '/b[ae]{1,2}t/{print $0}'
# 无输出,a和e共出现三次,超出范围。
4、管道符号
管道符号允许检查数据流时,用逻辑OR方式指定正则表达式引擎要用的两个或多个模
式。如果任何一个模式匹配了数据流文本,文本就通过测试;如果没有模式匹配,则数据流文本
匹配失败。
使用管道符号的格式如下:expr1|expr2|...
echo "The cat is asleep" | gawk '/cat|dog/{print $0}'
# 输出:The cat is asleepecho "The dog is asleep" | gawk '/cat|dog/{print $0}'
# 输出:The dog is asleepecho "The sheep is asleep" | gawk '/cat|dog/{print $0}'
# 输出:无# 正则表达式和管道符号之间不能有空格,否则会被认为是正则表达式模式的一部分。
echo "He has a hat." | gawk '/[ch]at|dog/{print $0}'
# 输出:He has a hat.
# 这个例子会匹配数据流文本中的cat、hat或dog。
5、表达式分组
正则表达式模式可以用圆括号进行分组。
echo "Sat" | gawk '/Sat(urday)?/{print $0}'
# 输出:Sat
echo "Saturday" | gawk '/Sat(urday)?/{print $0}'
# 输出:Saturday
# 问号表示括号内数据出现0次或1次。
echo "cat" | gawk '/(c|b)a(b|t)/{print $0}'
# 输出:cat
echo "cab" | gawk '/(c|b)a(b|t)/{print $0}'
# 输出:cab
echo "bat" | gawk '/(c|b)a(b|t)/{print $0}'
# 输出:bat
echo "bab" | gawk '/(c|b)a(b|t)/{print $0}'
# 输出:bab
echo "tab" | gawk '/(c|b)a(b|t)/{print $0}'
# 无输出
echo "tac" | gawk '/(c|b)a(b|t)/{print $0}'
# 不匹配,无输出
# 模式(c|b)a(b|t)会匹配第一组中字母的任意组合以及第二组中字母的任意组合