当前位置: 首页 > 科技观察

awk:强大的文本分析工具

时间:2023-03-11 22:49:50 科技观察

awk是一种流式编辑器,它对文档中的行进行操作并逐行执行。awk可以非常方便高效地对文档和字符进行操作,达到我们想要的格式。它非常强大,我在shell脚本中经常使用它来处理字符串。以下是在工作中使用awk的一些更频繁的用法。1.截取文档中的一个部分的示例命令如下:#head-n2test.txt|awk-F':''{print$1}'rootbin在这个例子中,-F选项用于指定定界符。如果不加-F选项,则使用空格或制表符作为分隔符。print是打印的动作,用于打印某个字段。$1是第一个字段,$2是第二个字段,依此类推。但是$0是特殊的,它表示整行:#head-n2test.txt|awk-F':''{print$0}'root:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologin注意awk的格式,-F后面是单引号,单引号是分隔符。打印动作必须用{}括起来,否则会报错。print也可以打印自定义内容,但是自定义内容必须用双引号括起来,如下图:#head-n2test.txt|awk-F':''{print$1"#"$2"#"$3"#"$4}'root#x#0#0bin#x#1#12. 匹配字符或字符串,过滤掉文档中包含指定字符串的行。示例命令如下:#awk'/oo/'test.txtroot:x:0:0:root:/root:/bin/bashlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinmail:x:8:12:mail:/var/spool/mail:/sbin/nologinoperator:x:11:0:operator:/root:/sbin/nologinpostfix:x:89:89::/var/spool/postfix:/sbin/nologinsettroubleshoot:x:992:990::/var/lib/setroubleshoot:/sbin/nologin这个和sed的用法类似,可以实现grep的功能,但是没有彩色显示,而且用起来肯定不如grep方便。但是awk比sed有更强大的匹配,如下:#awk-F':''$1~/oo/'test.txtroot:x:0:0:root:/root:/bin/bashsettroubleshoot:x:992:990::/var/lib/setroubleshoot:/sbin/nologin可以匹配某个段,其中~表示匹配。另外awk也可以匹配多次,如下图:#awk-F':''/root/{print$1,$3}/test/{print$1,$3}'test.txtroot0operator11test1006在本例中,匹配完root后,awk再次匹配test,只打印匹配到的段。3、 条件运算符有时候,在匹配字符的时候,需要给出限定条件,比如第三段中的0。示例命令如下:#awk-F':''$3=="0"'/etc/passwdroot:x:0:0:root:/root:/bin/bash在awk中,我们可以使用逻辑符号来判断,比如==等于,也可以理解为完全匹配。此外还有>、>=、<、<=、!=等。值得注意的是,在与数字进行比较时,如果要比较的数字是用双引号括起来的,那么awk不会认为它们是数字,但作为字符,并且没有双引号,它们将被视为数字。示例命令如下:#awk-F':''$3>="500"'/etc/passwd|head-n5shutdown:x:6:0:shutdown:/sbin:/sbin/shutdownhalt:x:7:0:halt:/sbin:/sbin/haltmail:x:8:12:mail:/var/spool/mail:/sbin/nologinnobody:x:65534:65534:内核溢出用户:/:/sbin/nologindbus:x:81:81:Systemmessagebus:/:/sbin/nologin在这个例子中,阿明想打印出uid大于等于500的行,但是结果并不理想。这是因为awk把所有的数字都当作字符对待,就像上一章说的排序原则一样。然而,如果你不加双引号,你会得到想要的结果:#awk-F':''$3>=500'/etc/passwd|head-n5nobody:x:65534:65534:KernelOverflowUser:/:/sbin/nologinsystemd-coredump:x:999:997:systemdCoreDumper:/:/sbin/nologinpolkitd:x:998:996:polkitd的用户:/:/sbin/nologingeoclue:x:997:995:User对于geoclue:/var/lib/geoclue:/sbin/nologinunbound:x:996:991:UnboundDNS解析器:/etc/unbound:/sbin/nologin#awk-F':''$7!="/sbin/nologin"'/etc/passwdroot:x:0:0:root:/root:/bin/bashsync:x:5:0:sync:/sbin:/bin/syncshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownhalt:x:7:0:halt:/sbin:/sbin/haltaminglinux:x:1000:1000:aminglinux:/home/aminglinux:/bin/bash在上面的例子中,!=表示不匹配,除了for除了对某一段中的字符进行逻辑比较外,还可以在两个段之间进行逻辑比较。如下:#awk-F':''$3<$4'/etc/passwdadm:x:3:4:adm:/var/adm:/sbin/nologinlp:x:4:7:lp:/var/spool/lpd:/sbin/nologinmail:x:8:12:mail:/var/spool/mail:/sbin/nologinames:x:12:100:games:/usr/games:/sbin/nologinftp:x:14:50:FTPUser:/var/ftp:/sbin/nologin此外,还可以使用&&和||,分别代表“与”和“或”。&&用法如下:#awk-F':''$3>"5"&&$3<"7"'/etc/passwdshutdown:x:6:0:shutdown:/sbin:/sbin/shutdownnobody:x:65534:65534:KernelOverflowUser:/:/sbin/nologintss:x:59:59:trousers包用来对tcsd守护程序进行沙箱处理的帐户:/dev/null:/sbin/nologin||用法如下:#awk-F':''$3>1000||$7=="/bin/bash"'/etc/passwdroot:x:0:0:root:/root:/bin/bashnobody:x:65534:65534:内核溢出用户:/:/sbin/nologinaminglinux:x:1000:1000:aminglinux:/home/aminglinux:/bin/bash4。awk的内置变量awk常用的变量有OFS、NF和NR。OFS和-F选项的功能相似,也是用来定义分隔符的,不过是在输出的时候定义的。NF表示用定界符分隔后有多少段。NR代表行号。OFS的用法示例如下:#head-5/etc/passwd|awk-F':''{OFS="#"}{print$1,$3,$4}'root#0#0bin#1#1daemon#2#2adm#3#4lp#4#7还有更高级的用法:#awk-F':''{OFS="#"}{if($3>=1000){print$1,$2,$3,$4}}'/etc/passwdnobody#x#65534#65534aminglinux#x#1000#1000变量nf的具体用法如下:#head-n3/etc/passwd|awk-F':''{printNF}'777#head-n3/etc/passwd|awk-F':''{print$NF}'/bin/bash/sbin/nologin/sbin/nologin其中NF是多少个部分,$NF是最后一个部分的值。NR变量的具体用法如下:#head-n3/etc/passwd|awk-F':''{printNR}'123我们也可以使用NR作为判断条件,如下:#awk'NR>40'/etc/passwdinsights:x:978:976:RedHatInsights:/var/lib/insights:/sbin/nologinsshd:x:74:74:特权分离SSH:/var/empty/sshd:/sbin/nologinavahi:x:70:70:AvahimDNS/DNS-SDStack:/var/run/avahi-daemon:/sbin/nologintcpdump:x:72:72::/:/sbin/nologinaminglinux:x:1000:1000:aminglinux:/home/aminglinux:/bin/bashNR也可以配合段匹配使用,如下:#awk-F':''NR<20&&$1~/roo/'/etc/passwdroot:x:0:0:root:/root:/bin/bash5.awk中的数学运算awk可以改变段值,示例命令如下:#head-n3/etc/passwd|awk-F':''$1="root"'rootx00root/root/bin/bashrootx11bin/bin/sbin/nologinrootx22daemon/sbin/sbin/nologinawk您还可以对每个段的值进行数学运算。示例命令如下:#head-n2/etc/passwdroot:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologin#head-n2/etc/passwd|awk-F':''{$7=$3+$4}'#head-n2/etc/passwd|awk-F':''{$7=$3+$4;打印$0}'rootx00root/root0binx11bin/bin2awk也可以计算某段的总和,示例命令如下:#awk-F':''{(tot=tot+$3)};END{printtot}'/etc/passwd84699这里的END是awk特有的表示所有行都执行完毕的语法如下:#awk-F':''{if($1=="root"){print$0}}'/etc/passwdroot:x:0:0:root:/root:/bin/bash其实awk可以写成脚本文件,有其独特的语法。awk中可以使用if判断和for循环,但是在日常的管理工作中用到这么复杂的语句并不常见。最后附上常用正则字符的解释。.表示任意字符,如空格、特殊符号等。*表示*前面有0个或多个字符,例如a*表示0个a或多个a。.*表示任意数量的任意字符,这是贪心匹配。+表示+前面有1个或多个字符,如a+表示a,aa,aaa...?表示?前面有1个或0个字符。{}里面是一个范围,比如{1,5}表示{}前面有1~5个字符。|表示任一个,例如a|b是a或b。[]表示其中的任意字符,如[abc]表示a或b或c。此外,还可以使用范围[0-9]表示任意数字,使用[a-z]表示任意小写字母。^表示开始。$表示结束。本文节选自《跟阿铭学 Linux(第4版)》一书。