Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3024235
  • 博文数量: 272
  • 博客积分: 5544
  • 博客等级: 大校
  • 技术积分: 5496
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-08 00:48
个人简介

  每个人都要有一个骨灰级的爱好,不为金钱,而纯粹是为了在这个领域享受追寻真理的快乐。

文章分类

全部博文(272)

文章存档

2015年(2)

2014年(5)

2013年(25)

2012年(58)

2011年(182)

分类: LINUX

2011-08-10 15:13:31

数据:
100,lucy@163.com,200
330,lily@sina.com,400
325,tom@sina.com,500
325,tom@sina.com,800
587,bob@sohu.com,200
235,jim@163.com,400
235,jim@163.com,900
 
要求相邻的两行第一字段的ID是相同的话,就用后面一行的第3字段去减前面一行,如果不相同就直接输出,并在后面打印OK:
100,lucy@163.com,200 OK
330,lily@sina.com,400 OK
325,tom@sina.com,300
587,bob@sohu.com,200 OK
235,jim@163.com,500
 
 
非数组版:
  1. awk 'BEGIN{FS=OFS=","}i==1{if($1==x){$3=$3-y;print;i=0;next}else{print z" OK"}}{x=$1;y=$3;z=$0;i=1}END{if(i==1)print z" OK"}' file

[解析]

  第一行,开始因为i的值为0,则执行后面没有pattern的{action},把第一行的第1字段,第3字段和整行内容分别赋给x,y,z,并且设置i的值为1,到第二行去匹配第1字段是否等于上一行,不等于的话就打印上一行内容,并加上OK,然后又把第二行的值赋给x,y,z,到了第三行,匹配if条件了,则把第3字段的值去减上一行的值,然后打印本行,设置i等于0并跳过后面的语句,这样做的目的是让下一行和下下一行之间去比较,而不是又是下一行和本行之间比较,这样就会打印多余的行,因为本行内容已经相减后输出到屏幕,下一行内容和本行不匹配的话那又将输出本行内容,这就不符合要求了。所以执行到下一行时,因为i=0,则不执行后面的语句,而执行x,y,z的赋值并把i赋值为1,i在这个其中就相当一个开关作用,控制语句的执行。最后那个END也很有道理,如果最后一行和前一行不匹配,那么打印前一行内容,因为是最后一行,并没有语句来执行最后一行的打印,那么内容会缺最后一行,又如果最后一行和上一行内容匹配,则打印了最后一行和相减的值那就没什么问题,但是我们要考虑全面的情况,所以在END中来执行最后一行是否打印,如果最后一行和上一行匹配,它已经被输出了,那么那时候i的值为0,如果不匹配最后执行i=1,我们又利用好了这个开关来看是否打印最后一行。



数组版:

  1. awk -F, '{n=$1FS$2;a[n]=$3"-"a[n];if(!b[n]++)c[++j]=n}END{for(i=0;i++<j;){split(a[c[i]],m,"-");print c[i]","m[1]-m[2](m[2]?"":" OK")}}' file

[解析]

它的原理呢是把每行的$1,$2用变量n来保存,然后放入数组a中,再把$3的值和数组a[n]用“-”连接起来,当然如果是 n 特征的第一行,a[n]的值是为空的,后面的if判断是为了保证最后的输出顺序和原文一致,在最后END用for取出数组a的内容,再通过“-”把数组a的每个内容分割到数组m中,然后打印下标(即$1,$2),判断“-”后面的内容是否为空,如果为空,那证明是唯一的一个特征行并打印OK,不为空则完成相减。

阅读(2668) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

yestreenstars2013-01-08 17:21:25

awk 'BEGIN{FS=OFS=","}{if($1==a){$3=$3-b;print;s="";next}if($1!=a&&s)print s" OK";a=$1;b=$3;s=$0}'

horizonhyg2011-08-11 10:51:47

说实话看的我很纠结。。