分类求和示例
2010-07-13 06:47:41 阿炯

现有如下列表数据:
a       1
b       2
c       3
e       4
a       5
b       6
c       7
e       8      
sort 一下,让后将第一列相同元素所对应的值相加
像如下:
a    6
....
-------------------------------
假设脚本名mysort.sh, 内容如下:
代码:
#!/bin/sh
sed -n '1,2p' $1
sed '1,2d' $1 | awk '{ array[$1] += $2 }
END { for (i in array)
print i, array[i]
}'  # | sort
则运行如下: $ mysort.sh

note:
1. 为了保留前两行,只得用sed分离然后分别处理
2. awk的数组不保留顺序,需要排列的话,则将 'sort' 前的'#'去掉即可
-------------------------------
$ perl -lane '$sum{$F[0]} += $F[1]; END { print "$_ $sum{$_}" foreach sort keys %sum };' guilei.txt
a 6
b 8
c 10
e 12
-------------------------------
awk '{if(NR>2)a[$1]+=$2;else print}END{for(i in a)printf i" "a[i]"\n"}'
awk '{a[$1]+=$2}END{for(i in a)print i,a[i]}'
-------------------------------
perl: sum an array
$total_in_array += $_ foreach @array ;

当前链接数据统计:
netstat -n | awk '/^tcp/ {++s[$NF]} END {for(a in s) print a, s[a]}'
状态:描述
CLOSED:无连接是活动的或正在进行
LISTEN:服务器在等待进入呼叫
SYN_RECV:一个连接请求已经到达,等待确认
SYN_SENT:应用已经开始,打开一个连接
ESTABLISHED:正常数据传输状态
FIN_WAIT1:应用说它已经完成
FIN_WAIT2:另一边已同意释放
ITMED_WAIT:等待所有分组死掉
CLOSING:两边同时尝试关闭
TIME_WAIT:另一边已初始化一个释放
LAST_ACK:等待所有分组死掉

netstat -n | awk '/^tcp/ {++state[$NF]} END {for(key in state) print key,"\t",state[key]}'
会得到类似下面的结果,具体数字会有所不同:
CLOSE_WAIT      41
TIME_WAIT      2294
ESTABLISHED      95
LAST_ACK      1
FIN_WAIT1      1

也就是说,这条命令可以把当前系统的网络连接状态分类汇总。
-------------------------------
先来看看netstat:
netstat -n
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State
tcp        0      0 123.123.123.123:80      234.234.234.234:12345   TIME_WAIT

你实际执行这条命令的时候,可能会得到成千上万条类似上面的记录,不过我们就拿其中的一条就足够了。
-------------------------------
再来看看awk:
/^tcp/
滤出tcp开头的记录,屏蔽udp, socket等无关记录。

state[]
相当于定义了一个名叫state的数组

NF
表示记录的字段数,如上所示的记录,NF等于6

$NF
表示某个字段的值,如上所示的记录,$NF也就是$6,表示第6个字段的值,也就是TIME_WAIT

state[$NF]
表示数组元素的值,如上所示的记录,就是state[TIME_WAIT]状态的连接数

++state[$NF]
表示把某个数加一,如上所示的记录,就是把state[TIME_WAIT]状态的连接数加一

END
表示在最后阶段要执行的命令

for(key in state)
遍历数组

print key,"\t",state[key]
打印数组的键和值,中间用\t制表符分割,美化一下。
-------------------------------
统计当前Win32系统上的TCP链接类型和数目的程序:
#!perl -w
use strict;

my %state =();
my @lines = split("\n", `netstat -n -a`);
foreach (@lines){
my $addr = "([0-9]+).([0-9]+).([0-9]+).([0-9]+):([0-9]+)";
if ($_ =~ /TCP[\s]+$addr[\s]+$addr[\s]+([\w]+)/){
$state{$11}++;
}
}

my ($key, $value);
print "$key=$value\n" while (($key,$value) = each %state);
-------------------------------
现在来统计一下lvs主控端上的链接数:
看lvs成员上的链接数
ipvsadm -l -n -c | awk '/^TCP/ {++s[$NF]} END {for(a in s) print a, s[a]}'
ipvsadm -l -n -c | awk '/^TCP/ {++s[$4]} END {for(a in s) print a}'|sort -n

打印出前10个链接数最多的ip地址
ipvsadm -l -n -c | awk '/^TCP/ {++s[$4]} END {for(a in s) print a}'|cut -d: -f1|awk '{++t[$1]} END {for(b in t) print b,t[b]}'|sort -nk2 -r|head

该文章最后由 阿炯 于 2012-04-27 10:04:53 更新,目前是第 2 版。