设为首页 收藏本站
查看: 1405|回复: 1

[经验分享] Linux awk用法

[复制链接]

尚未签到

发表于 2019-2-18 08:48:16 | 显示全部楼层 |阅读模式
  在学习awk之前我们应该都学过sed,grep,tr,cut等等命令,这些命令都是为了方便我们对Linux下文本和数据的处理,但是我们会发现很多时候这些命令并不能一下子就完全解决我们的需求,很多时候我们都需要使用管道符结合这些命令来使用,今天我就给大家介绍一个命令awk,他就能很好的解决我们对文本和数据处理的需求,使我们一条命令就解决很多问题。

一、awk命令简介
  awk被称为文本处理三剑客之一,其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。实际上 AWK 的确拥有自己的语言: AWK 程序设计语言 , 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。
所以说awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。

二、awk命令格式及选项
  语法形式
awk [options] 'script' var=value file(s)
awk [options] -f scriptfile var=value file(s)
常用命令选项
-F fs   fs指定输入分隔符,fs可以是字符串或正则表达式,如-F:
-v var=value   赋值一个用户定义变量,将外部变量传递给awk
-f scripfile  从脚本文件中读取awk命令
-m[fr] val   对val值设置内在限制,-mf选项限制分配给val的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。

三、awk的原理
  awk 'BEGIN{ commands } pattern{ commands } END{ commands }'

第一步:执行BEGIN{ commands }语句块中的语句;
第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ commands }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
第三步:当读至输入流末尾时,执行END{ commands }语句块。
  BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中。
  END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块。
  pattern语句块中的通用命令是最重要的部分,它也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块。

四、awk 基本用法
  awk的调用有三种方式
1.命令行方式
awk [-F  field-separator]  'commands'  input-file(s)
其中,commands 是真正awk命令,[-F域分隔符]是可选的。 input-file(s) 是待处理的文件。
在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。
  2.shell脚本方式
awk 'BEGIN{ print "start" } pattern{ commands } END{ print "end" }' file
一个awk脚本通常由:BEGIN语句块、能够使用模式匹配的通用语句块、END语句块3部分组成,这三个部分是可选的。任意一个部分都可以不出现在脚本中,脚本通常是被单引号或双引号中,例如:
  awk 'BEGIN{ i=0 } { i++ } END{ print i }' filename
awk "BEGIN{ i=0 } { i++ } END{ print i }" filename
  3.将所有的awk命令插入一个单独文件,然后调用
  awk -f awk-script-file input-file(s)
其中,-f选项加载awk-script-file中的awk脚本,input-file(s)跟上面的命令行方式是一样的。
我们通过几个简单的示例来进一步了解awk的用法

[root@localhost ~]# awk '{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
.........................................................................
[root@localhost ~]# echo 123|awk '{print "hello,awk"}'
hello,awk
[root@localhost ~]# awk '{print "hi"}' /etc/passwd
hi
hi
hi
hi
hi
hi
hi
hi
hi
.........................................................................

  我们指定/etc/passwd作为输出文件,执行awk时,它就会依次对/etc/passwd中的每一行执行print命令。

awk工作流程是这样的:读入有'\n'换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域。默认域分隔符是"空白键" 或 "[tab]键",所以$1表示登录用户,$3表示登录用户ip,以此类推。如

打印/etc/passwd下所有的用户名
[root@localhost ~]# awk -F: '{print $1}' /etc/passwd
root
bin
daemon
adm
........................................................................
打印/etc/passwd下所有的用户名及UID
[root@localhost ~]# awk -F: '{print $1,$3}' /etc/passwd
root 0
bin 1
daemon 2
........................................................................
以username: XXX  uid: XXX格式输出
[root@localhost ~]# awk -F: '{print "username: " $1 "\t\tuid: "$3}' /etc/passwd
username: root      uid: 0
username: bin       uid: 1
username: daemon        uid: 2
........................................................................
五、awk内置变量


变量
描述




\$n
当前记录的第n个字段,字段间由FS分隔


\$0
完整的输入记录


ARGC
命令行参数的数目


ARGIND
命令行中当前文件的位置(从0开始算)


ARGV
包含命令行参数的数组


CONVFMT
数字转换格式(默认值为%.6g)ENVIRON环境变量关联数组


ERRNO
最后一个系统错误的描述


FIELDWIDTHS
字段宽度列表(用空格键分隔)


FILENAME
当前文件名


FNR
各文件分别计数的行号


FS
字段分隔符(默认是任何空格)


IGNORECASE
如果为真,则进行忽略大小写的匹配


NF
一条记录的字段的数目


NR
已经读出的记录数,就是行号,从1开始


OFMT
数字的输出格式(默认值是%.6g)


OFS
输出记录分隔符(输出换行符),输出时用指定的符号代替换行符


ORS
输出记录分隔符(默认值是一个换行符)


RLENGTH
由match函数所匹配的字符串的长度


RS
记录分隔符(默认是一个换行符)


RSTART
由match函数所匹配的字符串的第一个位置


SUBSEP
数组下标分隔符(默认值是/034)
  示例

[root@localhost ~]# echo -e "line1 f2 f3\nline2 f4 f5\nline3 f6 f7" | awk '{print "Line No:"NR", No of fields:"NF, "$0="$0, "$1="$1, "$2="$2, "$3="$3}'
Line No:1, No of fields:3 $0=line1 f2 f3 $1=line1 $2=f2 $3=f3
Line No:2, No of fields:3 $0=line2 f4 f5 $1=line2 $2=f4 $3=f5
Line No:3, No of fields:3 $0=line3 f6 f7 $1=line3 $2=f6 $3=f7
  使用print $NF可以打印出一行中的最后一个字段,使用$(NF-1)则是打印倒数第二个字段,其他以此类推:

[root@localhost ~]# echo -e "line1 f2 f3\n line2 f4 f5" | awk '{print $NF}'
f3
f5
[root@localhost ~]# echo -e "line1 f2 f3\n line2 f4 f5" | awk '{print $(NF-1)}'
f2
f4
  统计/etc/passwd:文件名,每行的行号,每行的列数,对应的完整行内容:

[root@localhost ~]# awk  -F ':'  '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd
filename:/etc/passwd,linenumber:1,columns:7,linecontent:root:x:0:0:root:/root:/bin/bash
filename:/etc/passwd,linenumber:2,columns:7,linecontent:bin:x:1:1:bin:/bin:/sbin/nologin
filename:/etc/passwd,linenumber:3,columns:7,linecontent:daemon:x:2:2:daemon:/sbin:/sbin/nologin
  统计/etc/passwd文件中的命令行参数ARGC,文件行号FNR,字段分隔符FS,一条记录的字段数目NF,已经读出的记录数(默认是行号)NR

[root@localhost ~]# awk -F: 'BEGIN{printf "%4s %4s %4s %4s %4s %4s\n","FILENAME","ARGC","FNR","FS","NF","NR";printf "---------------------------------------------\n"} {printf "%4s %4s %4s %4s %4s %4s\n",FILENAME,ARGC,FNR,FS,NF,NR}'  /etc/passwd
FILENAME ARGC  FNR   FS   NF   NR
---------------------------------------------
/etc/passwd    2    1    :    7    1
/etc/passwd    2    2    :    7    2
/etc/passwd    2    3    :    7    3
六、awk高级用法
  1.awk赋值运算
赋值语句运算符:= += -= *= /= %= ^= **=
  例如:a+=5;等价于a=a+5

[root@localhost ~]# awk 'BEGIN{a=5;a+=5;print a}'
10
  2.awk正则运算
输出包含有root的行,并打印用户名和UID及原行内容

[root@localhost ~]# awk -F: '/root/ {print $1,$3,$0}' /etc/passwd
root 0 root:x:0:0:root:/root:/bin/bash
operator 11 operator:x:11:0:operator:/root:/sbin/nologin
  我们发现找到了两行,如果我们想找root开头的行就要这样写:awk -F: '/^root/' /etc/passwd
  3.awk三目运算

[root@localhost ~]# awk 'BEGIN{a="b";print a=="b"?"ok":"err"}'
ok
[root@localhost ~]# awk 'BEGIN{a="b";print a=="c"?"ok":"err"}'
err
  三目运算其实就是一个判断运算,如果为真则输出?后的内容,如果为假则输出:后的内容
4.awk的循环运用
if语句运用
[root@localhost ~]# awk 'BEGIN{ test=100;if(test>90){ print "vear good";} else{print "no pass";}}'
vear good
每条命令后用;结尾
while循环运用
计算从1累加到100的值

[root@localhost ~]# awk 'BEGIN{test=100;num=0;while(i

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-673765-1-1.html 上篇帖子: linux中grep的用法 下篇帖子: Linux中sed的用法
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表