awk:枚举基于另一个公共字段的字段

时间:2021-03-22 11:17:11

标签: arrays 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 中,然后搜索 array1 来实现通过迭代来自 array2 的元素。

2 个答案:

答案 0 :(得分:4)

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
}

答案 1 :(得分:3)

GNU datamash

$ datamash -W -t' ' -g1,2 collapse 3 <ip.txt
uid1 ip1 tag1,tag2
uid2 ip2 tag3,tag4,tag5
  • -W 使用空格/制表符作为输入字段分隔符
  • -t' ' 空格作为输出字段分隔符
  • -g1,2 组基于字段 12
  • collapse 3 对字段 3 执行的操作