awk的学习

来源:互联网 发布:淘宝众筹不发货怎么办 编辑:程序博客网 时间:2024/06/10 05:51
awk学习:
  • 其中单引号中的被大括号括着的就是awk的语句,注意,其只能被单引号包含。
  • 其中的$1..$n表示第几例。注:$0表示整个行。
zhangxin@nimei:~/bashDir$ awk '{print $1,$4}' netstat.txt 
Active (w/o
Proto Local
tcp 192.168.100.250:54992
tcp 192.168.100.250:ssh
tcp6 ip6-localhost:41452
udp6 ip6-localhost:56931
udp6 ip6-localhost:51472
zhangxin@nimei:~/bashDir$ awk '$3==0 && $6=="CLOSE_WAIT"' netstat.txt 
tcp6       1      0 ip6-localhost:41452     ip6-localhost:ipp       CLOSE_WAIT

其中的“==”为比较运算符。其他比较运算符:!=, >, <, >=, <=

再加上格式化输出:

zhangxin@nimei:~/bashDir$ awk '$3==0 && $6=="CLOSE_WAIT"||NR==1 {printf "%-20s %-20s %s\n",$4,$5,$6} ' netstat.txt 
(w/o                 servers)             
ip6-localhost:41452  ip6-localhost:ipp    CLOSE_WAIT
内建变量

说到了内建变量,我们可以来看看awk的一些内建变量:

$0当前记录(这个变量中存放着整个行的内容)$1~$n当前记录的第n个字段,字段间由FS分隔FS输入字段分隔符 默认是空格或TabNF当前记录中的字段个数,就是有多少列NR已经读出的记录数,就是行号,从1开始,如果有多个文件话,这个值也是不断累加中。FNR当前记录数,与NR不同的是,这个值会是各个文件自己的行号RS输入的记录分隔符, 默认为换行符OFS输出字段分隔符, 默认也是空格ORS输出的记录分隔符,默认为换行符FILENAME当前输入文件的名字

怎么使用呢,比如:我们如果要输出行号:

zhangxin@nimei:~/bashDir$ awk '$3==0 && $6~"ESTABLIS"||NR==1 {printf "%02s %s %-20s %-20s %s\n",NR,FNR,$4,$5,$6}' netstat.txt 
 1 1 (w/o                 servers)             
 3 3 192.168.100.250:54992 localhost:ssh        ESTABLISHED
 6 6 ip6-localhost:56931  ip6-localhost:51472   ESTABLISHED
 7 7 ip6-localhost:51472  ip6-localhost:56931   ESTABLISHED
指定分隔符
zhangxin@nimei:~/bashDir$ awk 'BEGIN{FS=":"}{print $1,$3,$6}' /etc/passwd|head
root 0 /root
daemon 1 /usr/sbin
bin 2 /bin
sys 3 /dev
sync 4 /bin
games 5 /usr/games
man 6 /var/cache/man
lp 7 /var/spool/lpd
mail 8 /var/mail
news 9 /var/spool/news

上面的命令也等价于:(-F的意思就是指定分隔符)

zhangxin@nimei:~/bashDir$ awk -F: '{print $1,$3,$6}'|head /etc/passwd

注:如果你要指定多个分隔符,你可以这样来:

awk -F[:?]

再来看一个以\t作为分隔符输出的例子(下面使用了/etc/passwd文件,这个文件是以:分隔的):

zhangxin@nimei:~/bashDir$ awk -F: '{print $1,$3,$6}' OFS="\t" /etc/passwd|tail -n 3
zabbix  123     /var/run/zabbix/
nagios  1002    /home/nagios
ftp     124     /srv/ftp
字符串匹配

我们再来看几个字符串匹配的示例:

zhangxin@nimei:~/bashDir$ awk '$6~/ESTABLI/||NR==1' netstat.txt 
Active Internet connections (w/o servers)
tcp        0      0 192.168.100.250:54992   localhost:ssh           ESTABLISHED
tcp        0     52 192.168.100.250:ssh     wenjing.yeepay.co:56495 ESTABLISHED
udp6       0      0 ip6-localhost:56931     ip6-localhost:51472     ESTABLISHED
udp6       0      0 ip6-localhost:51472     ip6-localhost:56931     ESTABLISHED
zhangxin@nimei:~/bashDir$ awk '$6~/CLOSE/||NR==1' OFS="\t" netstat.txt 
Active Internet connections (w/o servers)
tcp6       1      0 ip6-localhost:41452     ip6-localhost:ipp       CLOSE_WAIT 

上面的第一个示例匹配ESTABLISTED状态, 第二个示例匹配字样CLOSE_WAIT的状态。其实 ~ 表示模式开始。/ /中是模式。这就是一个正则表达式的匹配。

awk'NR!=1{print > $6}'netstat.txt
这个语句非常有用,因为这个语句可以根据$6的不同重定向到不同的文件中加以分类,其中NR!=1表示表头不处理
$awk'NR!=1{if($6 ~/TIME|ESTABLISHED/) print >"1.txt";
elseif($6 ~/LISTEN/) print >"2.txt";
elseprint >"3.txt"}'netstat.txt

下面的命令计算所有的C文件,CPP文件和H文件的文件大小总和。

zhangxin@nimei:~/bashDir$ ls -l *.sh|awk '{sum+=$5} END{print sum}'
2548

我们再来看一个统计各个connection状态的用法:(我们可以看到一些编程的影子了,大家都是程序员我就不解释了。注意其中的数组的用法)

再来看看统计每个用户的进程的占了多少内存(注:sum的RSS那一列)

zhangxin@nimei:~/bashDir$ ps aux|awk 'NR!=1 {a[$1]+=$6} END{for(i in a) print i ", " a[i]"KB"}'
whoopsie, 7196KB
message+, 2492KB
kernoops, 1012KB
syslog, 1888KB
colord, 5724KB
rtkit, 1308KB
gitlog, 4KB
xrdp, 924KB
snmp, 3924KB
nobody, 1552KB
gitdaem+, 852KB
www-data, 5328KB
avahi, 2144KB
zhangxin, 705456KB
postfix, 3092KB
proxy, 22492KB
mysql, 53264KB
root, 201352KB
lp, 1984KB

在上面我们可以看到一个END关键字。END的意思是“处理完所有的行的标识”,即然说到了END就有必要介绍一下BEGIN,这两个关键字意味着执行前和执行后的意思,语法如下:

  • BEGIN{ 这里面放的是执行前的语句 }
  • END {这里面放的是处理完所有的行后要执行的语句 }
  • {这里面放的是处理每一行时要执行的语句}

假设有这么一个文件(学生成绩表):

zhangxin@nimei:~/bashDir$ cat score.txt 
Marry 2143 78 84 77
Jack 2321 66 78 45
Tom 2322 48 77 71
Mike 2537 87 97 95
Bob 2415 40 57 62

我们的awk脚本如下(当awk处理程序代码较大时可以这样写,以便重复使用而且便于阅读):

 #!/bin/awk -f
  2 BEGIN {
  3  math=0;
  4  english=0;
  5  computer=0;
  6  printf "-------------------------\n"
  7  }
  8 {
  9  math += $3
 10  english += $4
 11  computer += $5
 12 }
 13 END{
 14  printf "Total: %10d,%8d,%8d\n",math,english,computer
 15  printf "Avg:%10.2f,%8.2f.%8.2f\n",math/NR,english/NR,computer/NR
 16 }
 17 

我们来看一下执行结果:(也可以这样运行 ./cal.awk score.txt)

zhangxin@nimei:~/bashDir$ awk -f cal.awk score.txt 
-------------------------
Total:        319,     393,     350
Avg:     63.80,   78.60.   70.00
这里有一个特别注意的地方是:BEGIN后面需要紧跟{,END也是,其中大括号不能换行书写
大括号里面每条语句可以有分号可以没有
0 0
原创粉丝点击