AWK简明教程(2)

统计

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

1
2
$ ls -l  *.cpp *.c *.h | awk '{sum+=$5} END {print sum}'
2511401

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

1
2
3
4
5
6
7
$ awk 'NR!=1{a[$6]++;} END {for (i in a) print i ", " a[i];}' netstat .txt
TIME_WAIT, 3
FIN_WAIT1, 1
ESTABLISHED, 6
FIN_WAIT2, 3
LAST_ACK, 1
LISTEN, 4

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

1
2
3
4
5
6
$ ps aux | awk 'NR!=1{a[$1]+=$6;} END { for(i in a) print i ", " a[i]"KB";}'
dbus, 540KB
mysql, 99928KB
www, 3264924KB
root, 63644KB
hchen, 6020KB

脱掉内衣

awk脚本

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

  • BEGIN{ 这里面放的是执行前的语句 }

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

  • {这里面放的是处理每一行时要执行的语句}

为了说清楚这个事,我们来看看下面的示例:

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

1
2
3
4
5
6
$ cat score.txt
Marry   2143 78 84 77
Jack    2321 66 78 45
Tom     2122 48 77 71
Mike    2537 87 97 95
Bob     2415 40 57 62

我们的awk脚本如下(我没有写有命令行上是因为命令行上不易读,另外也在介绍另一种用法):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ cat cal . awk
#!/bin/awk -f
#运行前
BEGIN {
math = 0
english = 0
computer = 0
printf "NAME    NO.   MATH  ENGLISH  COMPUTER   TOTAL\n"
printf "---------------------------------------------\n"
}
#运行中
{
math+=$3
english+=$4
computer+=$5
printf "%-6s %-6s %4d %8d %8d %8d\n" , $1, $2, $3,$4,$5, $3+$4+$5
}
#运行后
END {
printf "---------------------------------------------\n"
printf "  TOTAL:%10d %8d %8d \n" , math, english, computer
printf "AVERAGE:%10.2f %8.2f %8.2f\n" , math /NR , english /NR , computer /NR
}

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

1
2
3
4
5
6
7
8
9
10
11
$ awk -f cal . awk score.txt
NAME    NO.   MATH  ENGLISH  COMPUTER   TOTAL
---------------------------------------------
Marry  2143     78       84       77      239
Jack   2321     66       78       45      189
Tom    2122     48       77       71      196
Mike   2537     87       97       95      279
Bob    2415     40       57       62      159
---------------------------------------------
TOTAL:       319      393      350
AVERAGE:     63.80    78.60    70.00
环境变量

即然说到了脚本,我们来看看怎么和环境变量交互:(使用-v参数和ENVIRON,使用ENVIRON的环境变量需要export)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ x=5
$ y=10
$ export y
$ echo $x $y
5 10
$ awk - v val=$x '{print $1, $2, $3, $4+val, $5+ENVIRON["y"]}' OFS= "\t" score.txt
Marry   2143    78      89      87
Jack    2321    66      83      55
Tom     2122    48      82      81
Mike    2537    87      102     105
Bob     2415    40      62      72

几个花活

最后,我们再来看几个小例子:

1
2
3
4
5
6
7
8
#从file文件中找出长度大于80的行
awk 'length>80' file
#按连接数查看客户端IP
netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr
#打印99乘法表
seq 9 | sed 'H;g' | awk - v RS= '' '{for(i=1;i<=NF;i++)printf("%dx%d=%d%s", i, NR, i*NR, i==NR?"\n":"\t")}'

自己撸吧

关于其中的一些知识点可以参看gawk的手册:

  • 内建变量,参看:http://www.gnu.org/software/gawk/manual/gawk.html#Built_002din-Variables

  • 流控方面,参看:http://www.gnu.org/software/gawk/manual/gawk.html#Statements

  • 内建函数,参看:http://www.gnu.org/software/gawk/manual/gawk.html#Built_002din

  • 正则表达式,参看:http://www.gnu.org/software/gawk/manual/gawk.html#Regexp

(全文完)


你可能感兴趣的:(linux,shell,awk)