【问题标题】:Join lines with similar first column连接具有相似第一列的行
【发布时间】:2017-10-17 18:04:04
【问题描述】:

文件:

A    20
A    35
B    13
C    14
C    49
C    58

预期输出:

A    20,35
B    13
C    14,49,58

我有一个如上所述的制表符分隔文件。我想将具有相同第一列的行与逗号组合。我知道如何组合这些行以给我一个制表符分隔的第二列,但我希望第 2 列中的组合值用逗号分隔。这是我使用的命令:

LC_ALL='C' awk -F'\t' -v OFS='\t' '{x=$1;$1="";a[x]=a[x]$0}END{for(x in a)print x,a[x]}' input.txt > output.txt

我尝试将-F'\t' 更改为-F',',但这似乎不起作用。

【问题讨论】:

    标签: unix awk


    【解决方案1】:
    awk '{ A[$1] = A[$1] d[$1] $2; d[$1] = ","} 
    END {for (i in A) print i, A[i]}' input.txt > output.txt
    

    解释A[$1] = A[$1] d[$1] $2; - 将设置一个关联数组,其索引为$1,值为A[$1] d[$1] $2。最初它将等于$2,因为未定义A[$1]d[$1]d[$1] 存储输出分隔符","

    END 块在循环中打印数组索引(唯一的第一列)和元素("," 分隔字符串)。

    【讨论】:

    • 这非常有效。你介意解释一下你做了什么吗?最后,我最终使用awk 'BEGIN {OFS = "\t"} { A[$1] = A[$1] d[$1] $2; d[$1] = ","} END {for (i in A) print i, A[i]}' 来保留第一个标签
    • for (i in A) 不保证输出将按照 OP 发布的顺序打印。
    • 是的。但是可以使用| sort -k ...
    【解决方案2】:

    这是另一个,采用分组输入文件

    $ awk -v OFS=, 'function pr() {if(p2) print p2; p1=$1; p2=$0}
                                  {if($1==p1) p2=p2 OFS $2; else pr()} 
                    END           {pr()}' file
    
    A       20,35
    B       13
    C       14,49,58
    

    【讨论】:

      【解决方案3】:
      $ cat infile
      A    20
      A    35
      B    13
      C    14
      C    49
      C    58
      
      $ awk '{a[$1]=($1 in a ? a[$1] ",":"") $2}END{for(i in a)print i,a[i]}' infile
      A 20,35
      B 13
      C 14,49,58
      

      解释:

      • a[$1] a 是数组,$1 是第一个字段,用作数组键/索引
      • $1 in a 如果数组 (a) 有索引,即$1,那么我们得到布尔真状态
      • a[$1] "," 如果上一步状态为真,则该索引的数组a 的内容将与第二个字段连接,否则:"" 只是第二个字段,当数组没有该索引时。
      • for(i in a)print i, a[i]遍历数组a,变量i作为key, 打印数组键和值。

      a[$1]=($1 in a ? a[$1] ",":"") $2可以写成如下,方便初学者阅读/理解。

      # if array a seen index $1 before then
      if($1 in a){
      
         # append with existing data
         a[$1] = a[$1] "," $2
      
      # else
      }else{
      
         # did not see before, lets just set new data
         a[$1] = $2
      
      }
      

      【讨论】:

        【解决方案4】:

        问题是它的多个空格而不是制表符

        awk -F'[[:space:]][[:space:]]+' -v OFS=' ' '{if(a[$1])a[$1]=a[$1]","$2; else a[$1]=$2;}END{for (i in a)print i, a[i];}' input.txt > output.txt
        

        【讨论】:

          【解决方案5】:

          简单地做。

          awk '{(a[$1])?a[$1]=a[$1]","$2:a[$1]=$2} END{for (i in a) print i"\t"a[i]}' infile
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-05-31
            • 2017-06-14
            • 2012-06-17
            • 2022-06-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多