Linux Command -- gawk

gawk是GUN AWK的简称, 是GNU Project 的 AWK 解释器的开放源代码实现。它集成于UNIX系统,是一种功能强大的文本操作和模式匹配语言。它是一种解释性的语言,不需要进行编译。
有两句对awk的总结说明写的非常好:

  1. AWK是一种文本处理和模式匹配语言,所以它通常称为”数据驱动的“语言,程序语句描述需要进行匹配和处理的输入数据,而不是程序操作步骤的序列;
  2. AWK 程序在其输入数据中搜索包含模式的记录、对该记录执行指定的操作,直到程序到达输入的末尾。

gawk通常由pattern和action组成,action写在{ }当中,pattern与action通常是相对应的,类似于以下的格式:

pattern {action} pattern {action}...

pattern与action都是允许省略的,但是不允许两个同时省略。
如果pattern省略了,那对输入数据的每一行都会执行action;如果action被省略了,那每个符合pattern的行都会被执行一个默认的action:{print},即打印此行数据。
一个{action }中可以包括多条操作语句,使用分号(;)分隔。
gawk的输出可以使用print,也可以使用printf,格式与C语言类似。


gawk常用的有两种方式,一种是在命令行中直接使用,另一种是将gawk的操作写入到文件中然后使用”-f“参数指定。
在命令行中直接使用也分为两种方式,一种是对文件的操作,另一种是对管道输入信息的操作。
gawk默认使用不定量个空白字符做为字段分隔符,当读入一行数据时,它会将数据中的所有字段存入变量中,可以使用$+数字的方式来引用字段,例如$1表示的是第1个字段的内容。如果执行ls -l | gawk '{print $1}',那输出的第1个字段的内容就是权限信息。
$0是一个特殊的变量,使用它会输出整行信息而不是单独的某个字段。


以confile文件来做测试,confile文件使用指令“ls -l /etc/*.conf | head > confile”来生成。

1、gawk '{print $1,$5}' confile

是的,gawk可以同时输出多个字段,而且可以调整字段的顺序,例如$7,$2,$9,所以使用gawk可以很快速的提取并格式化数据,然后生成新的文件。

2、gawk '/lib/ {print $9}' confile

这个是标准的gawk用法,即pattern {action}的方式,作用是提取出含有”lib“字串的行,并打印它的第9个字段。

3、gawk '/lib/ {print $9} /so/ {print $9}' confile

这个也是标准的gawk用法,pattern {action} pattern {action}方式,作用是提取出含有lib子串和so子串的行,并打印它们的第9个字段。

4、gawk '{FS=":";print $1}' /etc/passwd

这个是gawk的省略方式,省略了pattern,表示对输入的每一行数据都会执行action,作用是指定字段分隔符为”:“,输出第一个字段。


执行上面例4的时候,是不是发现第一行提取的数据并不是所希望的数据,这是为什么呢?
因为gawk是对每一行的数据进行处理,读入一行数据,然后进行action,所以例4中指定字段分隔符为”:“是在读入了第1行数据之后进行的,对第1行数据的处理仍然是使用的默认不定量个空白字符来做为分隔符,对第2行及以下的数据才是使用的我们指定的”:“分隔符来处理。
怎么解决这个问题呢?使用BEGIN和END操作。
BEGIN {action},在gawk读入数据之前的操作;
END {action},在gawk处理完所有数据之后的操作。
例4重写为:

gawk 'BEGIN {FS=":"} {print $1}' /etc/passwd

就可以解决第一行没有进行处理的问题了。
指定的字符分隔符可以使用符号、字符和单词等方式。


将重写的例4指令修改一下:

echo 'BEGIN {FS=":"} {print $1}' > a

然后重新运行gawk:

gawk -f a /etc/passwd

所得到的结果与重写后的例4是相同的,明白了吗?这就是将gawk的操作写入到文件中的操作方式。
当操作较多时,可以将操作依次写入到文件中,再使用-f参数来指定执行,这样会简洁许多。


常见的gawk变量:

NF:包含每个记录的字段个数,就是每行数据的字段数;
NR:包含当前的记录个数,就是当前是第几条记录;
FS:指定字段分隔符,也可以用“-F”参数来指定,“-F”参数不包含在pattern或action当中;
RS:记录分隔符;
OFS:输出字段分隔符;
ORS:输出记录分隔符;

仍然以confile作为测试文件:

1、gawk '{print NF}' confile

输出每行数据的字段数,因为NF记录的是每行数据的字段数,所以如果使用{print $NF}输出的就是最后一个字段。

2、gawk '/lib/ {print NR}' confile

检索出包含”lib“子串的记录是在哪一行上,打印出行号。

3、gawk -F ":" '/lib/' /etc/passwd

变量FS在之前的例子中已经有用过了,这里展示一下”-F“参数的用法。

4、gawk 'BEGIN {RS="."} //' confile

拿confile文件中的一条记录来进行说明,数据记录为:

-rw-r--r--. 1 root root    55 3月   6 2015 /etc/asound.conf

执行完gawk后显示为:

-rw-r--r--
 1 root root    55 3月   6 2015 /etc/asound
conf

用“.”号将记录进行了分隔,并显示了出来,从哪里做的显示动作?使用的是“//”,它表示pattern为空,使用默认的action即{print},就会将所有记录打印出来。

5、gawk '{OFS="**"}{print $1,$2}' confile

打印出来的字段1和字段2会使用“**”分隔。如果没有指定OFS,默认是以空白字符来做为间隔;但是当{print $1 $2}中间没有“,”分隔时,字段1和字段2会连接打印,此时即使指定OFS也不会产生效果。

6、gawk '{ORS="%%"} //' confile

默认的记录分隔符是换行符,当使用ORS重新指定后,新指定的分隔符会替代原本的换行符。


pattern可以使用正则表达式的匹配方式。
gawk同时也支持字段匹配模式,使用“~”和“!~”操作符,分别表示包含和不包含。

1、gawk '$9 ~ /lib/ {print}' confile

第9个字段若包含“lib”则打印记录。

2、gawk '$9 !~ /lib/ {print}' confile

第9个字段若不包含“lib”则打印记录。
gawk也支持逻辑运算符与&&、或||、非!。

1、gawk '/lib/&&/it/ {print}' confile
例2、gawk '/lib/||/it/ {print}' confile
例3、gawk '!/lib/ {print}' confile

gawk可以使用范围模式,在两个pattern之间使得“,”号就可以指定一个范围。

1、gawk '/aso/,/e2f/' confile

搜索记录,从第一个包含“aso”子串的记录开始打印,直到遇见第一个包含“e2f”子串的记录时停止。若是没有满足第1个pattern的记录,则无论是否有满足第2个pattern的记录,都不会打印;若有满足第1个pattern的记录而没有满足第2个pattern的记录,则从满足第1个pattern的记录开始打印到结尾。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值