awk
zzx@zzx120:~/.ssh$ awk '{a[$1]++}END{for(i in a)print i,a[i]}' 1 统计相同$x出现的次数
awk -F ':' '{print $n}' a 和 awk 'BEGIN{FS=":"}{print $n}' a 是一样的
awk '{if (NF == 3)print}' b 和 awk -F ' ' '{if (NF == 3)print}' b 是一样的
zzx@zzx:~$ cat b
jack huaxue 90
tom huaxue 70
jack shuxue 99
tom shuxue 80
zzx@zzx:~$ awk '{a[$1]+=$3;b[$1]++}END{for(i in a)print i a[i]/b[i]}' b #计算平均成绩 i in a 或者 i in b 都行
tom75
jack94.5
#!/bin/sh
mem=`free -m | awk 'NR==2{print $2}'`
ps aux | sort -k 4 -r | awk '$4 ~ /^[0-9]/ && $4>0 {print $4,$11}' | awk '{print $1/100*mem" "$2}' mem=$mem | awk '
{
a[$2] += $1;
k[$2]++;
total+=$1;
}
END{
for(i in a){ t=i; gsub(/.*\//, "",t);
print t" "a[i]"M"" " k[i]}
print "Memory Total: "mem"MB, used: "total"MB, free: "mem-total"MB."
}' mem=$mem | sort -n -k2 -r
http://www.cnblogs.com/emanlee/p/3327576.html
文件file.txt (第一列号码--有重号的 ,第二列等级,第三列在线时长秒记)
123432 34 2345545
343245 23 2342345
234234 23 23423545
234523 65 234234
3423423 25 2342345
234234 23 2345234
。。。。。。省去若干行
用awk 取出3列值第一列号码,第二列等级要求小于30或者大于50 ,第三列要求相同号码的在线时间累积值。
一开始想半天没想到,为了做上面那题,自己周末从新看了一遍awk.. - -! ..终于做出来了。
]# awk '$2<30||$2>50{a[$1]+=$3}END{for(i in a)print i,a[i]}' file
3423423 2342345
234523 234234
234234 25768779
343245 2342345
awk 还可以去重而且顺序不变
cat a
WuHan
WuHan
WuHan
WuHan
beijing
beijing
huhehaote
huhehaote
SHenZHen
SHenZHen
beijing
huhehaote
huhehaote
SHenZHen
SHenZHen
# cat a|awk '{a[$1]}END{for(i in a) print i}'
WuHan
huhehaote
beijing
SHenZHen
http://president.blog.51cto.com/4990508/854647
zzx@zzx:~$ cat a|awk '{a[$1]+=1}END{for(i in a) print i,a[i]}'
1
huhehaote 4
SHenZHen 4
WuHan 5
beijing 3
cat 1
有一个文件是QQ号到手机号的绑定关系,一行一个关系,格式如下: cat file 11235334: 13443253456 11235335: 13443253457 11235336: 13443253458 11235333: 13443253458 11235336: 13443253459 11235334: 13443253452 要求统计出每个QQ绑定了几个手机,输出到一个文件里。格式如下: |
11235333: 1
13443253458
11235334: 2
13443253452
13443253456
11235335: 1
13443253457
11235336: 2
13443253458
13443253459
答案一:
# cat file|awk '{a[$1]+=1;b[$0]=$2}END{for (i in a){print i,a[i];for(j in b)if(j~i)print b[j]}}'
答案二:
]# awk 'BEGIN{FS=": "}{a[$1]++;b[$0]=$1}END{for(i in a){print "["i"]",a[i];for(j in b){if(b[j]==i){print substr(j,11)}}}}' file
答案三:
awk -F ':' '{a[$1]+=1;b[$1]=b[$1]"\n"$2}END{for(i in a) print i,"\n"a[i],b[i]"\n"}' file.txt
答案四:
#!/bin/bash
for qq in `cat qq.txt|awk -F":" '{print $1}'|sort|uniq`
do
echo "[$qq]"
grep $qq qq.txt|wc -l
echo -e "\n"
grep $qq qq.txt|awk -F":" '{print $2}'
done
sort qq.tel| awk -F':' '{if(tmp!=$1) {tmp=$1;print "["tmp"]";} print $2;}' #tmp可以换成其他字符 判断tmp是否不等于 不等于就把$1赋值给tmp 打印tmp的值"tmp“ 打印$2
分类如下:
[12334]
13510014336
12343453453
...........
[12099]
13598989899
12343454544
............
sort 11.txt |awk '{if(tmp!=$1){tmp=$1;print "["tmp"]"}print $2}'
awk '{if(){print }else{ print }}' file # uptime |awk '{if($4~/day/) {print $3$4$5$6} else{print $3$4}}'|sed 's/,$//' 打印系统启动了多长时间 print加文字时"文字"
awk 'NR==1||NR==3 {print $0}' 1.txt # 第一和第三行 sed -n "1,3p" 1.txt 1到3行
awk -F" " '{if($2>6){print $0}}' 1.txt
zzx@zzx120:~/test1$ echo 1|awk '{if($0~/[0-9]/) print "ok"}'
ok
匹配第七个字段以mp4结尾的第三个域
awk '$7~/mp4$/ {print $3}'
$ awk '$1 ~/[0-9][0-9]$/ {print $1}' test-----如果第一个域以两个数字结束就打印这个记录。
$ awk '$1 != 10' test-----如果第一个域不等于10就打印该行
$ awk '$1 == 100 || $2 < 50' test-----如果第一个域等于100或者第二个域小于50,则打印该行。
$ awk '/^root/,/^mysql/' test----打印以正则表达式root开头的记录到以正则表达式mysql开头的记录范围内的所有记录。如果找到一个新的正则表达式root开头的记录,则继续打印直到下一个以正则表达式mysql开头的记录为止,或到文件末尾。
四、BEGIN&END
对某一列求和awk 'BEGIN{sum=0} {sum=$9+sum} END {print "sum " sum}' data
awk '{num+=$1} END {print unm}'
求平均数 awk 'BEGIN{sum=0} {sum=$9+sum} END {print "average " sum / FNR}' access_log
从第6个字段开始输出awk '{for(i=6; i<NF; ++i){printf "%s,",$i};printf "%s\n", $NF}' access_log
从第6个字段开始输出awk '{for(i=6; i= 6 && NR <=100) printf "%d: %s\n", NR, $7}' access_log
五、IF条件和循环
awk '{if ($NF>3) print $0}' xxx.txt 最后一列大于3行打印
awk '{if (length($2)>3) print $0}' xxx.txt 打印第二个字段长度大于3的行
$awk '{if($2 ~ /^baidu$/) print $0}' xxx.txt 打印第二列为百度的字段 $awk '$2 ~ /^baidu$/ {print $0}' xxx.txt
awk有三种循环:while循环;for循环;special for循环。
$ awk '{ i = 1; while ( i <= NF ) { print NF,$i; i++}}' test。变量的初始值为1,若i小于可等于NF(记录中域的个数),则执行打印语句,且i增加1。直到i的值大于NF.
$ awk '{for (i = 1; i<NF; i++) print NF,$i}' test。作用同上。
breadkcontinue语句。break用于在满足条件的情况下跳出循环;continue用于在满足条件的情况下忽略后面的语句,直接返回循环的顶端。如:
{for ( x=3; x<=NF; x++)
if ($x<0){print "Bottomed out!"; break}}
{for ( x=3; x<=NF; x++)
if ($x==0){print "Get next item"; continue}}
next语句从输入文件中读取一行,然后从头开始执行awk脚本。如:
{if ($1 ~/test/){next}
else {print}
}
awk '{if($1>3) print $0}' a.txt
【awk】想把两列交换怎么办?用awk '{print $2,$1}' filename吧,在管道操作里面可以 ...操作|awk '{print $2,$1}' ,多列操作同理,还可以这样计算两列之和什么的 操作|awk '{print $2+$1}'
zzx@zzx103:~/dhcptest$ cat a.txt
1 2 3
2 3 5
2 3 55
3
323
22
zzx@zzx103:~/dhcptest$ cat a.txt|awk '{sum+=$1} END {print "Sum = ", sum}' #求和
Sum = 353
zzx@zzx103:~/dhcptest$ cat a.txt|awk '{sum+=$1} END {print "Average = ", sum/NR}' #求平均
Average = 58.8333
zzx@zzx103:~/dhcptest$ cat a.txt|awk 'BEGIN {max = 0} {if ($1>max) max=$1 fi} END {print "Max=", max}' #最大 好像不一定写fi
Max= 323
zzx@zzx103:~/dhcptest$ cat a.txt | awk 'BEGIN {min = 1999999} {if ($1<min) min=$1 fi} END {print "Min=", min}' #最小
Min= 1
zzx@zzx103:~$ cat at.txt
1113 22
33465 33
a 44
NO 445 55
r 334
NO
zzx@zzx103:~$ awk -F" " '$1~/N/ {print $1}' at.txt # ~代表匹配
NO
NO
zzx@zzx103:~$ awk '$1~/N/ {print $1}' at.txt
NO
NO
zzx@zzx134:~/dhcptest$ cat aaa
a b c d aa bb:11:33
1 2 3 4 cc dd:22:44
zzx@zzx134:~/dhcptest$ awk '{print $6}' aaa
bb:11:33
dd:22:44
zzx@zzx134:~/dhcptest$ awk -F'\t' '{print $1}' aaa
a b c d
1 2 3 4
zzx@zzx134:~/dhcptest$ awk -F':' '{print $1}' aaa
a b c d aa bb
1 2 3 4 cc dd
zzx@zzx134:~/dhcptest$ awk -F':' 'BEGIN{print "start"}{print $1} END{print "end##"}' aaa
start
a b c d aa bb
1 2 3 4 cc dd
end##
zzx@zzx134:~/dhcptest$ awk -F':' 'BEGIN{a=1;b=2}{print $(a+b)}' aaa
33
44
zzx@zzx134:~$ awk 'BEGIN {FS=":"} $1~"root"' /etc/passwd # !~不匹配
root:x:0:0:root:/root:/bin/bash
zzx@zzx134:~$ awk 'BEGIN {FS=":"} {if($3<$4) print $0}' /etc/passwd
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
libuuid:x:100:101::/var/lib/libuuid:/bin/sh
syslog:x:101:103::/home/syslog:/bin/false
zzx@zzx134:~$ awk 'BEGIN {FS=":"} {if($3==10||$4==10) print $0}' /etc/passwd
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh #精确匹配
zzx@zzx134:~$ awk 'BEGIN {FS=":"} {if($3~10||$4~10) print $0}' /etc/passwd
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
libuuid:x:100:101::/var/lib/libuuid:/bin/sh#模糊匹配
zzx@zzx134:~/dhcptest$ awk '/^$/{print x++}' aaa #匹配空白行
0
1
2
3
zzx@zzx134:~/dhcptest$ awk '/^$/{print ++x}' aaa
1
2
3
4
zzx@zzx134:~/dhcptest$ awk '/^$/{print x+=1}' aaa
1
2
3
4
zzx@zzx134:~/dhcptest$ awk 'BEGIN {FS=":"} {print NF,NR,$0} END{print FILENAME}' aaa
6 1 a b c d aa bb:11:33:::kkk
6 2 1 2 3 4 cc dd:22:44:::qqq
0 3
0 4
0 5
0 6
aaa
zzx@zzx134:~/dhcptest$ awk '{print NF,NR,$0} END{print FILENAME}' aaa
6 1 a b c d aa bb:11:33:::kkk
6 2 1 2 3 4 cc dd:22:44:::qqq
0 3
0 4
0 5
0 6
aaa
awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。
last -n5|awk '{print $1}' #last -4 也行
cat /etc/passwd |awk -F ':' '{print $1}' #等于 cat /etc/passwd |cut -d':' -f1 显示/etc/passwd的账户 awk -F: '{print $1}' 也行
cat /etc/passwd |awk -F ':' '{print $1"\t"$7}' #显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以tab键分割
cat /etc/passwd |awk -F ':' 'BEGIN {print "name,shell"} {print $1","$7} END {print "blue,/bin/nosh"}' #显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以逗号分割,而且在所有行添加列名name,shell,在最后一行添加"blue,/bin/nosh"。 BEGIN END 注意是大写 工作流程是这样的:先执行BEGING,然后读取文件,读入有/n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域,随后开始执行模式所对应的动作action。接着开始读入第二条记录······直到所有的记录都读完,最后执行END操作
搜索/etc/passwd有root关键字的所有行 #搜索支持正则,例如找root开头的: awk -F: '/^root/' /etc/passwd
#awk -F: '/root/' /etc/passwd
统计某个文件夹下的文件占用的字节数
ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size}'
[end]size is 8657198
如果以M为单位显示:
ls -l |awk 'BEGIN {size=0;} {size=size+$5;} END{print "[end]size is ", size/1024/1024,"M"}'
[end]size is 8.25889 M
注意,统计不包括文件夹的子目录。
统计某个文件夹下的文件占用的字节数,过滤4096大小的文件(一般都是文件夹):
ls -l |awk 'BEGIN {size=0;print "[start]size is ", size} {if($5!=4096){size=size+$5;}} END{print "[end]size is ", size/1024/1024,"M"}'
[end]size is 8.22339 M
显示/etc/passwd的账户
awk -F ':' 'BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}' /etc/passwd
0 root
1 daemon
2 bin
3 sys
4 sync
5 games
......