Chinaunix

标题: awk 统计 [打印本页]

作者: z421941982    时间: 2013-01-05 16:47
标题: awk 统计
本帖最后由 z421941982 于 2013-01-06 21:40 编辑

现有文件内容如下:
  1. a        111
  2. b        111
  3. c        111
  4. d        111
  5. b        222
  6. c        222
  7. d        222
复制代码
文件中第一列为文本(名称), 第二列为数值(金额), 现想得到以下结果:
  1. a b 1
  2. a c 1
  3. a d 1
  4. b a 1
  5. b c 2
  6. b d 2
  7. c a 1
  8. c b 2
  9. c d 2
  10. d a 1
  11. d b 2
  12. d c 2
复制代码
统计规则如下:
a c 1  意思为:  第一列的名称中 a 与 c 在第二列的金额 相等的 记录有 1个. ( 注 根据文件中 第1行记录和第3行记录 得到的结果)
b c 2  意思为:  第一列的名称中 b 与 c 在第二列的金额 相等的 记录有 2个. ( 注 根据文件中 第2,3行记录和第5,6行记录 得到的结果)



作者: dahaoshanhe    时间: 2013-01-05 17:31
没看明白是下面这个意思不?
先把文件复制一下 cp f1 f2
  1. awk 'NR==FNR{a[$1" "$2]=$0;next}
  2. {
  3.    for(i in a)
  4.       {
  5. print a[i],"   "$0
  6.        }
  7.   }' f1 f2  |
  8. awk '
  9. {
  10.   if($2==$4)
  11.     {print $1,$3,"1"}
  12.    else
  13.    {print $1,$3," 2" }
  14. }'  
  15. d  a  1
  16. c  a  1
  17. d  a  2
  18. b  a  1
  19. c  a  2
  20. a  a  1
  21. b  a  2
  22. d  b  1
  23. c  b  1
  24. d  b  2
  25. b  b  1
  26. c  b  2
  27. a  b  1
  28. b  b  2
  29. d  c  1
  30. c  c  1
  31. d  c  2
  32. b  c  1
  33. c  c  2
  34. a  c  1
  35. b  c  2
  36. d  d  1
  37. c  d  1
  38. d  d  2
  39. b  d  1
  40. c  d  2
  41. a  d  1
  42. b  d  2
  43. d  b  2
  44. c  b  2
  45. d  b  1
  46. b  b  2
  47. c  b  1
  48. a  b  2
  49. b  b  1
  50. d  c  2
  51. c  c  2
  52. d  c  1
  53. b  c  2
  54. c  c  1
  55. a  c  2
  56. b  c  1
  57. d  d  2
  58. c  d  2
  59. d  d  1
  60. b  d  2
  61. c  d  1
  62. a  d  2
  63. b  d  1
复制代码

作者: z421941982    时间: 2013-01-06 16:11
回复 2# dahaoshanhe


你写这个我也没看懂, 干嘛把文件拷成两份?

   
作者: huangyu_945    时间: 2013-01-06 17:27
呵呵  没看懂正常
作者: davidbeckham921    时间: 2013-01-06 17:46
感觉很难的样子,要用二维数组和俩循环判断才能输出来楼主想要的。
作者: davidbeckham921    时间: 2013-01-06 18:44
本帖最后由 davidbeckham921 于 2013-01-07 10:44 编辑
  1. awk '{a[$1]++;b[$1,a[$1]-1]=$2;a[$1]>m?m=a[$1]:m=m}0END{for(i in a) for (j in a) for(k=0;k<=m;k++)if( i!=j && b[i,k]==b[j,k] && b[i,k]!="") printf "%s\t%s\t%s\n",i,j,b[j,k]}' urfile\
  2. |awk '{a[$1" "$2]++}END{for(i in a)print i" "a[i]}'
复制代码
写完已经大小便失禁,生活不能自理了,求高手简化。

如果没有理解错你的意思的话结果应该是,跟你期望的结果稍有偏差,感觉你给的答案是不对的。比如:b d 都有111和222,所以应该是 b d 2
a b 1
a c 1
a d 1
b a 1
b c 2
b d 2
c a 1
c b 2
c d 2
d a 1
d b 2
d c 2

求高手解释,能否把管道后的awk合并到前面?!俩END怎么搞?!
作者: yestreenstars    时间: 2013-01-06 19:47
我也来写一个吧
  1. awk '{a[$1];b[$2];c[$1""$2]}END{for(i in a){for(j in a){if(i!=j){for(k in b){if((i""k in c)&&(j""k in c))n++}print i,j,n;n=""}}}}'
复制代码
运行结果如下:
  1. [root@localhost ~]# cat i
  2. a        111
  3. b        111
  4. c        111
  5. d        111
  6. b        222
  7. c        222
  8. d        222
  9. [root@localhost ~]# awk '{a[$1];b[$2];c[$1""$2]}END{for(i in a){for(j in a){if(i!=j){for(k in b){if((i""k in c)&&(j""k in c))n++}print i,j,n;n=""}}}}' i
  10. a b 1
  11. a c 1
  12. a d 1
  13. b a 1
  14. b c 2
  15. b d 2
  16. c a 1
  17. c b 2
  18. c d 2
  19. d a 1
  20. d b 2
  21. d c 2
  22. [root@localhost ~]#
复制代码

作者: z421941982    时间: 2013-01-06 21:39
回复 6# davidbeckham921
  你的答案是正确的, 要的就是这个结果



   
作者: z421941982    时间: 2013-01-06 21:47
回复 7# yestreenstars


    神一样的代码, 看一遍都晕了, 就是要这个结果!!!
作者: dahaoshanhe    时间: 2013-01-07 09:39
回复 8# z421941982


    你的问题写的还没有人家给出正确答案的人写的代码好懂  神呀你
作者: blackold    时间: 2013-01-07 09:45
回复 6# davidbeckham921


    大小便失禁,牛!
作者: davidbeckham921    时间: 2013-01-07 10:33
yestreenstars 发表于 2013-01-06 19:47
我也来写一个吧运行结果如下:


真心牛掰啊,学习了!~~

这样好!
作者: Shell_HAT    时间: 2013-01-07 10:37
回复 6# davidbeckham921


    把代码放到code标签里面吧,否则论坛程序会弄丢一些字符。
作者: davidbeckham921    时间: 2013-01-07 10:40
回复 13# Shell_HAT


    呵呵好!知道了老大。
作者: blackold    时间: 2013-01-07 13:51
回复 6# davidbeckham921


    Sorry!

昨天没时间看。

后面可以这样简化:
  1. {
  2.     a[$1]++;
  3.     b[$1,a[$1]-1]=$2;
  4.     a[$1]>m?m=a[$1]:m=m
  5. }
  6. END{
  7.     for(i in a)
  8.         for (j in a)
  9.             for(k=0;k<=m;k++)
  10.                 if( i!=j && b[i,k]==b[j,k] && b[i,k]!="")
  11.                     c[i" "j]++;
  12.     for(i in c) print i,c[i];
  13. }
复制代码

作者: davidbeckham921    时间: 2013-01-07 15:35
blackold 发表于 2013-01-07 13:51
回复 6# davidbeckham921


谢谢黑哥,明白了,昨天试了半天拼END没想到;就搞定了。
作者: 423497786    时间: 2014-02-08 16:42
  1. [root@localhost ~]# cat 1.txt
  2. a        111
  3. b        111
  4. c        111
  5. d        111
  6. b        222
  7. c        222
  8. d        222
  9. [root@localhost ~]# awk '{
  10. >   a[$1,++b[$1]]=$2
  11. > }
  12. > END{
  13. >   for (i in b)
  14. >     for (j in b) {
  15. >       c=0
  16. >       if (i!=j) {
  17. >         for (m=1;m<=b[i];m++)
  18. >           for (k=1;k<=b[j];k++)
  19. >             if (a[i,m]==a[j,k])
  20. >               ++c
  21. >         print i,j,c
  22. >       }
  23. >     }   
  24. > }' 1.txt
  25. a b 1
  26. a c 1
  27. a d 1
  28. b a 1
  29. b c 2
  30. b d 2
  31. c a 1
  32. c b 2
  33. c d 2
  34. d a 1
  35. d b 2
  36. d c 2
  37. [root@localhost ~]#
复制代码

作者: elu_ligao    时间: 2014-02-09 19:12
  1. awk '{a[$2]=a[$2]?a[$2]FS$1:$1}END{for(i in a){l=split(a[i],b);for(j=1;j<=l;++j)for(k=j+1;k<=l;++k){s[b[k]" "b[j]]++;s[b[j]" "b[k]]++}}for(i in s)print i,s[i]}' file | sort
复制代码





欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2