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
......

 

posted on 2014-11-25 18:09  寒星12345678999  阅读(434)  评论(2编辑  收藏  举报