awk

2018-09-09  本文已影响15人  tracy_668

awk是一个强大的文本分析工具,简单地说,它是把文件逐行读入,以空格为默认分割符将每行切片,切开的部分再进行分析、处理。

使用方法

awk 'pattern + {action}'  filenames

案例说明:

wusong@ubuntu:~$ last -n 5
wusong   pts/9        192.168.58.1     Sat Sep  8 19:06   still logged in
wusong   pts/9        192.168.58.1     Sat Sep  8 06:47 - 18:11  (11:24)
wusong   pts/10       192.168.58.1     Fri Sep  7 20:24 - 21:21  (00:56)
wusong   pts/9        192.168.58.1     Fri Sep  7 19:26 - 21:21  (01:55)
wusong   pts/9        192.168.58.1     Fri Sep  7 06:45 - 18:56  (12:11)

wtmp begins Mon Sep  3 17:27:36 2018

wusong@ubuntu:~$ last -n 5 |awk '{print $1}'
wusong
wusong
wusong
wusong
wusong

wtmp

  awk会读取有'\n'换行符分割的一条记录,然后将记录按指定的域分隔符划分域,0表示所有的域,1表示第一个域,$n表示第n个域。

cat /etc/passwd |awk  -F ':'  'BEGIN {print "name,shell"}  {print $1","$7} END {print "blue,/bin/nosh"}'
name,shell
root,/bin/bash
daemon,/bin/sh
bin,/bin/sh
sys,/bin/sh
....
blue,/bin/nosh

 如果有BEGIN,就会先执行BEGIN,然后读取文件,读入有\n换行分割符的一条记录,对每条记录执行action,直到所有的记录都读完,最后执行end操作。

awk -F: '/root/' /etc/passwd // 搜索含有root关键字的行
root:x:0:0:root:/root:/bin/bash
awk -F: '/root/{print $7}' /etc/passwd
/bin/bash

awk内置变量

ARGC 命令行参数个数
ARGV 命令行参数排列
ENVIRON 支持队列中系统环境变量的使用
FILENAME awk浏览的文件名
FNR 浏览文件的记录数
FS 设置输入域分隔符,等价于命令行 -F选项
NF 浏览记录的域的个数
NR 已读的记录数
OFS 输出域分隔符
ORS 输出记录分隔符
RS 控制记录分隔符

wusong@ubuntu:~$ 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:daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
filename:/etc/passwd,linenumber:3,columns:7,linecontent:bin:x:2:2:bin:/bin:/usr/sbin/nologin
filename:/etc/passwd,linenumber:4,columns:7,linecontent:sys:x:3:3:sys:/dev:/usr/sbin/nologin
filename:/etc/passwd,linenumber:5,columns:7,linecontent:sync:x:4:65534:sync:/bin:/bin/sync
filename:/etc/passwd,linenumber:6,columns:7,linecontent:games:x:5:60:games:/usr/games:/usr/sbin/nologin
filename:/etc/passwd,linenumber:7,columns:7,linecontent:man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
filename:/etc/passwd,linenumber:8,columns:7,linecontent:lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
filename:/etc/passwd,linenumber:9,columns:7,linecontent:mail:x:8:8:mail:/var/mail:/usr/sbin/nologin

可以使用printf代替print,让代码更加简洁
 awk  -F ':'  '{printf("filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n",FILENAME,NR,NF,$0)}' /etc/passwd

awk除了内置变量,还可以自定义变量。

awk '{count++;print $0;} END{print "user count is ", count}' /etc/passwd
wusong@ubuntu:~$ ls -l | awk 'BEGIN {size=0;} {size=size+$5;}END{print "size is", size}'
size is 63307
wusong@ubuntu:~$ ls -l | awk 'BEGIN {size=0;} {size=size+$5;}END{print "size is", size/1024/1024 " M"} '
size is 0.0603743 M  // 不包括文件夹的子目录
awk -F: 'BEGIN{count=0;} {name[count]=$1; count++;} END { for (i=0;i<NR;i++) print i, name[i]}' /etc/passwd

几个小例子

wusongs-MacBook-Pro:~ wusong$ netstat -n | awk '/^tcp/{++test[$NF]} END {for (a in test) print a, test[a]}'
CLOSE_WAIT 3
TIME_WAIT 1
ESTABLISHED 28

  S[]定义了一个名叫S的数组,在awk中,数组下标通常从 1 开始,而不是 0。
  NF当前记录里域个数,默认以空格分隔,如上所示的记录,NF域个数等于6
  $NF表示一行的最后一个域的值,$NF也就是$6,表示第6个字段的值,也即SYN_RECV或TIME_WAIT等。
  S[$NF] 表示数组元素的值,如上所示的记录,就是S[TIME_WAIT]状态的连接数++S[$NF]表示把某个数加一,如上所示的记录,就是把S[TIME_WAIT]状态的连接数加1
  END for(key in S)遍历S[]数组 print key,”\t”,S[key],打印数组的键和值,中间用\t制表符分割,显示好一些。

awk '{++S[$1]} END {for(i in S) print i, S[i]}' access.log | sort -k2 -r
10.0.0.41 3
10.0.0.47 2
10.0.0.46 2
10.0.0.42 2
10.0.0.43 1

wusong@ubuntu:~$ awk 'BEGIN{
    FS=":"
    printf("%-10s%-20s\n", "UserName", "HomeDir")
    print "=============================="
}
{
    printf("%-10s%-20s\n", $1, $6)
}
END{
    print "=============================="
    printf("User(s):%d\n", NR)
    print "=============================="
}' /etc/passwd

也可以将上述脚本写入listUser.awk这个文件,然后在命令行中执行:

awk -f listUser.awk /etc/passwd

透过现象看本质

image.png

上图为awk的基本流程,awk分为三个部分:

小结

本文主要介绍了awk的基本用法和一些小的案例以及awk流程分析,awk是一种功能极其强大的文本分析工具,值得深入研究。

上一篇下一篇

猜你喜欢

热点阅读