首页 > 解决方案 > awk:基于另一个公共字段枚举字段

问题描述

这很可能是用数组完成的,但我不知道如何构建逻辑。

输入:

uid1 ip1 tag1
uid1 ip1 tag2
uid2 ip2 tag3
uid2 ip2 tag4
uid2 ip2 tag5

期望的输出:

uid1 ip1 tag1,tag2
uid2 ip2 tag3,tag4,tag5

我在想,也许这可以通过将所有元素存储在 中array1,然后将uid+ip字段存储在 中,然后通过从 中迭代元素array2进行搜索来实现。array1array2

标签: arraysawk

解决方案


awk -v OFS=, '{
         k=$1 SUBSEP $2; 
         arr[k] = k in arr ? arr[k] OFS $3 : $0;
      }
      END{
         for(i in arr)
            print arr[i]
      }' infile

试验结果:

$ cat f1
uid1 ip1 tag1
uid1 ip1 tag2
uid2 ip2 tag3
uid2 ip2 tag4
uid2 ip2 tag5

$ awk -v OFS=, '{k=$1 SUBSEP $2; arr[k] = k in arr ? arr[k] OFS $3 : $0;}END{for(i in arr)print arr[i]}' f1
uid1 ip1 tag1,tag2
uid2 ip2 tag3,tag4,tag5

解释:

awk -v OFS=, '{                                   # output field separator
         # variable k contains field1 value 
         # and  SUBSEP - Multi-dimensional array separator 
         # and column 2 value

         k=$1 SUBSEP $2; 

         # arr -> array
         # if array key that is variable k already exists in array arr
         # then arr[k] will be existing content of arr[k]  plus
         # field separator (comma) and then field 3 contents
         # else entire row/record which is when array does not have index already

         arr[k] = k in arr ? arr[k] OFS $3 : $0;

      }
      END{                      # END block

         # iterate through array arr
         # and print array value

         for(i in arr)
            print arr[i]

      }' infile

下面的三元运算符

arr[k] = k in arr ? arr[k] OFS $3 : $0;

if(k in arr){
  arr[k] = arr[k] OFS $3
}else{
  arr[k] = $0
}

推荐阅读