linux命令awk基础用法整理

2016-11-30 20:07:03 6216

该文章主要是以案例来讲解awk的使用方法,以及延伸到一些实际生产环境中使用(比如统计进程整体cpu或内存负载等)
首先,我们后边的操作以/tmp/file为例,内容如下:

[root@21yunwei tmp]# cat file 
ll 34523452345 80 97 70
kk 78979797979 90 90 90
hh 78979879797 60 60 60
jj 23678236876 59 58 57
aa 78987897878 23 34 12

1,awk工作模式

awk 'BEGIN{ print "start"}  pattern { commands }  END{ print "end"}'   file

awk是迭代处理,即一行行的处理。比如我们打印第1个字段结果的处理过程:先取第一行的第一个字段,然后再取第二行的第一个字段。。。一直到处理完整个数据流。:

[root@21yunwei tmp]# cat file  |awk  '{print $1}'
ll
kk
hh
jj
aa

2,awk指定多个分隔符
awk默认是以空白为分隔符,如果有其他分隔符,我们需要使用-F’ ‘指定(类似cut -d’ ‘)。

[root@21yunwei /]# cat /etc/passwd | tail -2 |awk -F':' '{print $1}'
user19
user20

也可以指定多个分隔符,通过正则[]来匹配,如果多个相同符号,我们可以'[ ]+’来将相同符号认为一个.比如我们修改文件file成如下内容:

[root@21yunwei tmp]# cat file
ll:34523452345 80 97 70
kk:78979797979 90 90 90
hh 78979879797 60 60 60
jj 23678236876 59 58 57
aa 78987897878 23 34 12

现在我们要取第二列:

[root@21yunwei tmp]# cat file  |awk -F'[ :]' '{print $2}'
34523452345
78979797979
78979879797
23678236876
78987897878

如果我们前边变成两个冒号,就不可以这样写了,要写成:

[root@21yunwei tmp]# cat file  |awk -F'[ :]+' '{print $2}'

没有+号,则两个冒号的无法显示,认为两个冒号之前认为是空白。其中多个空白也需要+号。

延伸实际应用,取服务器网卡IP:

[root@web9 tmp]# ifconfig  eth0
eth0      Link encap:Ethernet  HWaddr 52:54:00:8B:CA:F2  
          inet addr:192.168.1.9  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::5054:ff:fe8b:caf2/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1

这个写法有很多,我们只举例awk,其他方式比如cut也可以获取。awk获取IP如下:

[root@21yunwei tmp]# ifconfig  eth0 | grep "t a" |awk -F'[ :]+' '{print $4}'
192.168.1.9
[root@21yunwei tmp]# ifconfig  eth0 | awk 'NR==2{print $0}' |awk -F'[ :]+' '{print $4}'
192.168.1.9

3,awk内置变量NF讲解
NF:每一行的字段数量,每一行的NF值可能不同也可能相同(number of filed)
比如我们查看file的最后一列和倒数第二列:

[root@21yunwei tmp]# cat file  |awk '{print $NF,$(NF-1)}'
70 97
90 90
60 60
57 58
12 34

4,awk内置变量NR讲解
NR:数据流的行数,number of recoding

值如下:

[root@21yunwei tmp]# awk  '{print NR}' file
1
2
3
4
5

举例我们分别打印第一行、打印2-4行:

[root@21yunwei tmp]# cat file |awk 'NR==1{print $0}'
ll 34523452345 80 97 70
[root@21yunwei tmp]# cat file |awk 'NR==2,NR==4{print $0}'
kk 78979797979 90 90 90
hh 78979879797 60 60 60
jj 23678236876 59 58 57
[root@21yunwei tmp]# cat file |awk 'NR>1&&NR<5{print $0}'
kk 78979797979 90 90 90
hh 78979879797 60 60 60
jj 23678236876 59 58 57
[root@21yunwei tmp]# cat file |awk 'NR!=1&& NR!=5{print $0}'
kk 78979797979 90 90 90
hh 78979879797 60 60 60
jj 23678236876 59 58 57

取一行的第一列,取第三行的第二列:

[root@21yunwei tmp]# cat file |awk 'NR==1{print $1} NR==3{print $2}'
ll
78979879797

扩展FNR,多个文件同时操作是分别记录文件行数。

5,awk的pattern介绍
pattern{action}pattern说白了就是一个判断,后边接action(动作),即'{}’ 花括号前边可以加一个判断,如果为真就执行后边的,如果是假,则不执行。具体可以参考上边行数判断取值。

比如’NR!=1&& NR!=5{print $0}’ ,其中NR!=1&& NR!=5就是pattern,{print $0}就是action

6,awk中BEGIN和END用法
BEGIN和END是一种特殊的模式,BEGIN是在pattern{action}首先执行,END是在pattern{action}执行后执行,即在文本处理前执行和文本执行后。执行效果如下:

[root@21yunwei tmp]# cat file |awk 'BEGIN{print "=====BEGIN======"}{print $0}END{print "=====END======"}'
=====BEGIN======
ll 34523452345 80 97 70
kk 78979797979 90 90 90
hh 78979879797 60 60 60
jj 23678236876 59 58 57
aa 78987897878 23 34 12
=====END======

用途:可以用于变量赋值、最后取值、输出表头和表尾提示等。
7,awk计算方法
里边的计算类似C语言的计算方法,可以直接使用。

例1,取3 4 5行的和,取平均数,将取的平均数取整。注意:awk的计算支出小数,如果取整可以int。

[root@21yunwei tmp]# cat file |awk '{print $0,$3+$4+$5,($3+$4+$5)/3,int(($3+$4+$5)/3)}'
ll 34523452345 80 97 70 247 82.3333 82
kk 78979797979 90 90 90 270 90 90
hh 78979879797 60 60 60 180 60 60
jj 23678236876 59 58 57 174 58 58
aa 78987897878 23 34 12 69 23 23
另一种写法:
[root@21yunwei tmp]# cat file |awk '{sum=$3+$4+$5;print $0,sum,sum/3,int(sum/3)}'
ll 34523452345 80 97 70 247 82.3333 82
kk 78979797979 90 90 90 270 90 90
hh 78979879797 60 60 60 180 60 60
jj 23678236876 59 58 57 174 58 58
aa 78987897878 23 34 12 69 23 23

例2,取第三个字段的总和并去平均值:

[root@21yunwei tmp]# cat file |awk '{total+=$3}END{print total,total/NR}' 
312 62.4

延伸生产环境使用,统计httpd占用内存整体使用情况(也可以统计cpu,其他进程一样):

[root@21yunwei tmp]# ps aux | grep httpd |awk '{total+=$4};END{print total}'
20.8

统计php-fpm的cpu和内存使用:

[root@21yunwei mysqlbak]# ps aux  |grep php-fpm|awk '{a+=$3;b+=$4}END{print "cpu:"a,"mem:"b}'
cpu:3.1 mem:12.2

8,awk中if用法
用法: awk ‘{if(判断语句)print ….}’,建议将if判断加入花括号内部,这样{}外部就还可以写入其他的模式判断语句,当然也可以进行嵌套。
我们取第三列大于等于60的整行输出:

[root@21yunwei tmp]# cat file |awk '{if($3>=60)print $0}'
ll 34523452345 80 97 70
kk 78979797979 90 90 90
hh 78979879797 60 60 60
以上结果等同于:
[root@21yunwei tmp]# cat file |awk '$3>=60{print $0}'
ll 34523452345 80 97 70
kk 78979797979 90 90 90
hh 78979879797 60 60 60

延伸:我们将/var/log/目录下大于25K的文件列出(当然find也是可以的):

[root@21yunwei log]# ll |awk '/^-/{if($5>25600){print $0}}'
-rw-------  1 root  root       328869 9月   2 02:30 cron
-rw-------  1 root  root       469313 8月   7 03:13 cron-20160807
-rw-------  1 root  root       465889 8月  14 03:34 cron-20160814
-rw-------  1 root  root       453704 8月  21 03:27 cron-20160821
-rw-------  1 root  root       452841 8月  28 03:25 cron-20160828
-rw-r--r--. 1 root  root       167384 10月 20 2015 dracut.log-20160101
-rw-r--r--. 1 root  root       295504 9月   1 23:57 lastlog
-rw-------  1 root  root       411506 8月  31 16:50 maillog
-rw-------  1 root  root       887248 8月   7 03:10 maillog-20160807
-rw-------  1 root  root       863595 8月  14 03:30 maillog-20160814
-rw-------  1 root  root       810424 8月  21 03:25 maillog-20160821
-rw-------  1 root  root       806775 8月  28 03:20 maillog-20160828
-rw-------  1 root  root     40093034 9月   2 02:33 messages
-rw-------  1 root  root     56538021 8月   7 03:13 messages-20160807
-rw-------  1 root  root     56686276 8月  14 03:34 messages-20160814
-rw-------  1 root  root     56529992 8月  21 03:26 messages-20160821
-rw-------  1 root  root     56520983 8月  28 03:25 messages-20160828
-rw-------  1 root  root       190881 8月   6 23:05 secure-20160807
-rw-------  1 root  root        62891 8月  12 20:56 secure-20160814
-rw-rw-r--. 1 root  utmp       392448 9月   1 23:57 wtmp

默认是字节,我们需要换算一下。25K=1014*25


9,awk中变量介绍

awk可以自己定义新变量,类似C语言方法,定义的变量方便我们调用比如:

[root@21yunwei tmp]# cat file|awk '{total+=$NF}END{print total}'
289

比如我们之前统计httpd占用内存百分比,也使用到了变量:

[root@21yunwei tmp]# ps aux | grep httpd |awk '{total+=$4};END{print total}'
20.8

10,awk中for循环使用
awk的for循环,类似C语言中的for循环。举例如下:

[root@21yunwei tmp]# cat file |awk '{for(i=1;i<NF-2;i++){print $i}}'
ll
34523452345
kk
78979797979
hh
78979879797
jj
23678236876
aa
78987897878

一行一行的处理,比如第一行,我们可以知道是i<3,即可i为1 2 ,则打印$1 $2两个字段。剩下每行也是打印$1 $2两个字段。
再弄一个取这个file?奇数列:

[root@21yunwei tmp]# cat file |awk '{for(i=1;i<=NF;i+=2){printf $i" "}print a}'
ll 80 70 
kk 90 90 
hh 60 60 
jj 59 57 
aa 23 12

注意事项:步长+2,printf不换行输出加空格,可以让其整行输出;后边输出一个空变量做换行。取偶数列则起始值改成2.

11,awk正则表达式

awk '/^abc/{....}' 以abc开头 
awk '!/^abc/{...}' 不是以abc开头
awk  '/abc/{...}' 包含abc字符串
awk '!/abc/{...}' 不包含abc
~:匹配,可以和上边的结合使用。

举例如下:

[root@21yunwei tmp]# cat file |awk '/^kk/{print $0}'
kk 78979797979 90 90 90
[root@21yunwei tmp]# cat file |awk '!/^kk/{print $0}'
ll 34523452345 80 97 70
hh 78979879797 60 60 60
jj 23678236876 59 58 57
aa 78987897878 23 34 12
[root@21yunwei tmp]# cat file |awk '/6/{print $0}'
hh 78979879797 60 60 60
jj 23678236876 59 58 57
[root@21yunwei tmp]# cat file |awk '!/6/{print $0}'
ll 34523452345 80 97 70
kk 78979797979 90 90 90
aa 78987897878 23 34 12
[root@21yunwei tmp]# cat file |awk '!/6/&amp;&amp; $1~/kk/{print $0}'
kk 78979797979 90 90 90
[root@21yunwei tmp]#

总结:awk是强大的工具,基本可以实现所有需要数据获取。有些时候grep、find、sed等可以相对实现功能,或其实现不了的功能awk也能实现。原则就是一个,满足功能需求的前提下什么方便使用什么。

提交成功!非常感谢您的反馈,我们会继续努力做到更好!

这条文档是否有帮助解决问题?

非常抱歉未能帮助到您。为了给您提供更好的服务,我们很需要您进一步的反馈信息:

在文档使用中是否遇到以下问题: