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

Posted

技术标签:

【中文标题】awk:基于另一个公共字段枚举字段【英文标题】:awk: enumerate fields based on another common field 【发布时间】:2021-06-19 00:49:35 【问题描述】:

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

输入:

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 中,然后通过迭代来自array2 的元素来搜索array1

【问题讨论】:

【参考方案1】:
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;ENDfor(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

【讨论】:

谢谢,它按预期工作。我不能说我可以破译整个代码,所以我可以更好地理解它是如何工作的。具体来说,这些部分:k=$1 SUBSEP $2arr[k] = k in arr ? arr[k] OFS $3 : $0 @one-liner 补充说明 @Akshay,感谢您分享精彩的答案。 真的很好解释【参考方案2】:

与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 执行的操作

【讨论】:

我不知道datamash,语法看起来更简单更干净,不幸的是它默认没有安装在我的目标环境中。不过会记住这一点,以备将来使用。

以上是关于awk:基于另一个公共字段枚举字段的主要内容,如果未能解决你的问题,请参考以下文章

Joshua Bloch 在 Effective Java 中解释的枚举类型

如何在Django中基于枚举为模型字段设置默认值?

基于枚举值设置对象中某些字段的设计模式。

枚举类常见漏洞解决

枚举类型和位标志

十数据库公共字段处理