本节内容:
awk 数组排序
我们知道,awk数组是关联数组,在使用for…in循环输出时,默认打印出来是无序数组。
例如:
4 test
1 this
2 is
3 a
如果需要按照顺序输出,通过键值定位方式输出。
1 this
2 is
3 a
4 test
一、通过内置函数(asort,asorti使用) awk 3.1以上版本才支持
1、asort使用说明
srcarrlen=asort[srcarr,dscarr] 默认返回值是:原数组长度,传入参数dscarr则将排序后数组赋值给dscarr.
a[100]=100;
a[2]=224;
a[3]=34;
slen=asort(a,tA);
for(i=1;i<=slen;i++)
{print i,tA[i];}
}'
1 34
2 100
3 224
asort只对值进行了排序,因此丢掉原先键值。
2、asorti 使用说明
a["d"]=100;
a["a"]=224;
a["c"]=34;
slen=asorti(a,tA);
for(i=1;i<=slen;i++)
{print i,tA[i],a[tA[i]];}
}'
1 a 224
2 c 34
3 d 100
asorti对键值 进行排序(字符串类型),将生成新的数组放入:tA中。
二、通过管道发送到sort排序
a[100]=100;
a[2]=224;
a[3]=34;
for(i in a)
{print i,a[i] | "sort -r -n -k2";}
}'
2 224
100 100
3 34
通过管道,发送到外部程序“sort”排序,-r 从大到小,-n 按照数字排序,-k2 以第2列排序。
通过将数据丢给第3方的sort命令,所有问题变得非常简单。如果以key值排序 –k2 变成 -k1即可。
a[100]=100;
a[2]=224;
a[3]=34;
for(i in a)
{print i,a[i] | "sort -r -n -k1";}
}'
100 100
3 34
2 224
三、自定义排序函数
awk自定义函数结构:
{
staction;
return value;
}
以上是:awk自定义函数表示方式,默认传入参数都是以引用方式传入,return值,只能是字符型或者数值型。 不能返回数组类型。 如果返回数组类型。需要通过形参 方式传入。再获得。
awk返回数组类型
二,排序函数
#key 排序类型 1是按照值排序 2按照键值
#datatype 比较类型 1按照数字排序 2按照字符串排序
#tarr 排序返回的数组
#splitseq 分割字符串 数组中键与值之间分割字符串
#return 数组长度
#实现思路,将原始数组a[‘a’]=100 排序后变成 a[1]=a分隔符100 ,然后按照下标递归显示内容。 本排序使用冒泡方式进行。
function sortArr(arr,key,datatype,tarr,splitseq)
{ if(key ~ /[^1-2]/)
{return tarr;}
for(k in arr)
{
tarr[++alen]=(k""splitseq""arr[k]);
} for(m=1;m<=alen;m++)
{
for(n=1;n<=alen-m-1;n++)
{
split(tarr[m],tm,splitseq);
split(tarr[n+1],tn,splitseq); tnum=tarr[m];
if(datatype==1)
{
if(tm[key]+0<tn[key]+0)
{
tarr[m]=tarr[n+1];
tarr[n+1]=tnum;
}
}
else
{
if((tm[key]"") < (tn[key]""))
{
tarr[m]=tarr[n+1];
tarr[n+1]=tnum;
}
}
}
}
return alen;
}
完整代码:
a["a"]=100;
a["b"]=110;
a["c"]=10;
splitseq="%%";
alen=sortArr(a,2,1,tarr,splitseq);
for(m=1;m<=alen;m++)
{
split(tarr[m],ta,splitseq);
print m,ta[1],ta[2];
}
}
function sortArr(arr,key,datatype,tarr,splitseq)
{ if(key ~ /[^1-2]/)
{return tarr;}
for(k in arr)
{
tarr[++alen]=(k""splitseq""arr[k]);
} for(m=1;m<=alen;m++)
{
for(n=1;n<=alen-m-1;n++)
{
split(tarr[m],tm,splitseq);
split(tarr[n+1],tn,splitseq); tnum=tarr[m];
if(datatype==1)
{
if(tm[key]+0<tn[key]+0)
{
tarr[m]=tarr[n+1];
tarr[n+1]=tnum;
}
}
else
{
if((tm[key]"") < (tn[key]""))
{
tarr[m]=tarr[n+1];
tarr[n+1]=tnum;
}
}
}
}
return alen;
}
' 1 b 110
2 a 100
3 c 10
总结:
以上便是awk数组排序一些方法。
对于少量数据排序,就性能而言,使用自定义函数性能要高,不需要另外再开启进程。
对于大量数据,建议使用排序的第2种方法。
本节内容:
awk 多行合并
本节介绍awk next语句的用法:
在循环逐行匹配,如果遇到next,就会跳过当前行,直接忽略下面语句。
而进行下一行匹配。
text.txt 内容是:
b
c
d
e
[root@ shell]$
2 b
4 d
当记录行号除以2余 1,就跳过当前行。下面的print NR,$0也不会执行。
下一行开始,程序有开始判断NR%2 值。这个时候记录行号是:2 ,就会执行下面语句块:'print NR,$0'
二,awk next使用实例:
要求:
文件:text.txt 格式:
httpd ok
tomcat ok
sendmail ok
web02[192.168.2.101]
httpd ok
postfix ok
web03[192.168.2.102]
mysqld ok
httpd ok
通过awk将输出格式变成:
web01[192.168.2.100]: tomcat ok
web01[192.168.2.100]: sendmail ok
web02[192.168.2.101]: httpd ok
web02[192.168.2.101]: postfix ok
web03[192.168.2.102]: mysqld ok
web03[192.168.2.102]: httpd ok
分析:
需要将包含有“web”行进行跳过,然后需要将内容与下面行合并为一行。
web01[192.168.2.100]: httpd ok
web01[192.168.2.100]: tomcat ok
web01[192.168.2.100]: sendmail ok
web02[192.168.2.101]: httpd ok
web02[192.168.2.101]: postfix ok
web03[192.168.2.102]: mysqld ok
web03[192.168.2.102]: httpd ok
小结:awk命令中,next在多行合并,以及选择性输出方面很方便,建议参考使用之。
本节内容:
awk查看ip连接数
例1:[xxx@localhost ~]
while("netstat -an"|getline){
if( $5 ~ /[1-255]/)
{
split($5,t1,":");
tarr[t1[1]]++;
}
}
for(k in tarr)
{
print k,tarr[k] | "sort -r -n -k2";
}
};'
说明:$5是netstat –an 第5个字段。默认就是对方连接ip以及端口。
例2,[xxx@localhost ~]$
time awk 'BEGIN{while("netstat -an"|getline){if( $5 ~ /[1-255]/){split($5,t1,":");tarr[t1[1]]++;}}for(k in tarr){print k,tarr[k] | "sort -r -n -k2";}};'
211.151.33.14 28
113.65.21.200 14
121.32.89.106 13
60.191.178.230 12
118.133.177.104 12
58.61.152.154 11
219.137.58.20 11
124.117.248.52 11
122.198.80.145 11
222.88.15.138 10
222.44.13.191 10
222.161.47.34 10
221.4.202.210 10
218.79.64.12 10
183.17.92.193 10
120.72.128.254 10
118.118.121.244 10
116.252.38.236 10
113.248.75.44 10
real 0m1.149s
user 0m0.032s
sys 0m1.055s