awk初步学习(不断总结)

1.输入文件中间多了换行符处理

这里写图片描述
  本来的文件是每行4个字段,但是有的行中间多了换行符,导致读出来的文件变成了这样。使用awk进行处理。

cat 222.txt|awk  'BEGIN{a=0}{   
    if((a+NF)<4){
        printf $0;a=a+NF
    }
    else{
        printf $0"\n";a=0
    }
}'

// cat 222.txt|awk  'BEGIN{a=0}{ 指令1 } 
    读取文件内容通过管道传递到后面使用awk进行处理
    BEGIN{a=0} 命令在初始化阶段就执行,所以a在最开始为0
    { 指令1 }  是awk在每行读取时需要执行的命令(awk是行读取并处理,防止内存爆炸)
NF表示的是读进来的行有多少列,如果小于指定的列数,打印,但是不换行,因为还有字段在下一行,并且a=现有列数。
继续读取下一行,和上一行不完整的列拼接起来,即执行的else。然后换行,并另a0.
当来一行是正常的行,直接打印。

  但是,如果是自己构造的数据,打印会出错,如下面的图:
这里写图片描述
  这是因为我们在构造数据的时候直接换行(如7之后的8,没有加上本应该有间隔符),而实际的业务表格是有这个间隔符的,且间隔符之后多了一个换行符导致形成多行,所以上诉代码在实际业务执行就不会两个数贴在一起。
  自己构造数据的时候可以在7之后加上对应的间隔符,或者代码改成如下形式:

自己构造的时候少了本应该的间隔符,所以打印的时候加上
cat 222.txt|awk  'BEGIN{a=0}{   
    if((a+NF)<4){
        printf $0" ";a=a+NF    //在$0后加了空格
    }
    else{
        printf $0"\n";a=0
    }
}'

这里写图片描述
  这样就正常了。

2.awk常见命令:

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

3.例题

1.该例题转载自:http://blog.chinaunix.net/uid-10540984-id-1185098.html
3 5 6 7
2 3 1 0
4 5 6 9
2 3 4 4
2 2 1 0
4 5 0 9
假如把2列和3列的值作为新的第5列,第5列的平均值为avg5,求第5列中大于avg5的行数。

1:
awk '{x+=$2+$3;a[NR]=$2+$3}END{y=x/NR;for(i in a){if(y<a[i])z++}print z}' file

[解析]
   这个题初看,觉得简单,仔细看又觉得有难度,否则腾讯这些大企业也不会出这么简单的题了,呵呵。首先来分析,第5列的值很好办 2+ 2 + 3,但是求平均值比较麻烦,麻烦的原因是只有最后END才可以通过累加的x的值来除以行数然后得出平均值,又有个一个新的问题,这时候已经END了,求出了平均值但是无法再从新历遍全文去比较每行的 2+ 2 + 3 是否大于该平均值,怎么着?总得有个东西来装 2+ 2 + 3 的结果吧,目的是将 2+ 2 + 3的结果放入一个容器,在END求出平均值后再拿出来判断比较,惯例请出我们的老朋友数组。最后的大家都能看懂了吧。
  
自己学习备注:
这里写图片描述
1.NR 是当前读的是第几行(从1)开始,NF是当前行有多少列;
2.a[NR]= 2+ 2 + 3 相当于一行一行的读,求和,并保存到a的数组中,且行号同步;
3.同一个{}内的语句不同指令用 “;” 分割;
3.END是读取完毕后的总的操作。

2:
awk 'BEGIN{while(getline<"file"){x+=$2+$3;i++};y=x/i}{if($2+$3>y)z++}END{print z}' file

[解析]

   这是7月22日更新的新命令,我新学会的一种处理手段,在BEGIN模块中利用 while(getline<”file”) 来提前历遍全文,在BEGIN中我们可以看到,我已经把 2+ 2 + 3的和累加给了x变量,但是求平均值必须要知道行数,怎么办呢?这时候在BEGIN中NR还是0,当然可以搞定了,我们这时候就不用NR自己建个变量来保存行数就好了嘛,这样我们可以顺利的在BEGIN模块中就已经求出了平均数了。然后按照正常的执行流程再逐行判断第2列和第3列的和是否大于这个平均数,最后打印统计结果。
2.转载至 https://blog.csdn.net/wangbran/article/details/81033371
有个一个文件 file,内容如下

1.1.1.1 st_000012 ajgoahgoahgoahgghg
2.2.2.2 st_000014 ajgoaoghaughughgu
3.3.3.3 st_000015 alfjoigrhuogrub
4.4.4.4 st_000016 ajgoaghkaahgoahgghg
1.1.1.1 st_000019 ajgoalllllghughgu
5.5.5.5 st_000015 alfjoigrhuogrub

  找到第一列中出现最多的ip,第二列中出现最多的用户名,必须要用awk

awk ‘BEGIN{max_h=0;max_i=0}{ip[$1]++;host[$2]++};END{for(i in ip){if(ip[i]>max_i){max_i=ip[i];ip_m=i}}print max_i,ip_m;for(j in host){if(host[j]>max_h){max_h=host[j];host_m=j}}print max_h,host_m}’ file

结果
2 1.1.1.1
2 st_000015

自己学习备注:
1.

awk '{ip[$1]++;host[$2]++}
END{
for(i in ip){print i,ip[i]};
print "................."
for(j in host){print j,host[j]}}' myfile

这里写图片描述
  ip[$1]相当于字典,将内容当成键值,出现次数为value,后面遍历输出就可以了。

补充grep、sed和awk的区别:

详见:https://www.cnblogs.com/-zyj/p/5763303.html
  grep、sed和awk都是文本处理工具,虽然都是文本处理工具单却都有各自的优缺点,一种文本处理命令是不能被另一个完全替换的,否则也不会出现三个文本处理命令了。只不过,相比较而言,sed和awk功能更强大而已,且已独立成一种语言来介绍。

grep:文本过滤器,如果仅仅是过滤文本,可使用grep,其效率要比其他的高很多;

sed:Stream EDitor,流编辑器,默认只处理模式空间,不处理原数据,如果你处理的数据是针对行进行处理的,可以使用sed;

awk:报告生成器,格式化以后显示。如果对处理的数据需要生成报告之类的信息,或者你处理的数据是按列进行处理的,最好使用awk。

即grep简单查询过滤比较快;sed可以对行进行处理,比如增加,修改,替换行中部分内容比较方便;awk生成一些报告,做一些统计,对行和列进行处理就使用awk要方便许多。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值