根據第 1 列合併同一文件中的多行

根據第 1 列合併同一文件中的多行

我仍在學習編程,並且嘗試了很多方法,但無法獲得正確的格式。我有一個製表符分隔文件有 17 列和許多(大約 50.000)行。該文件已按第一列排序。我想合併具有相同第一列 (A) 的行,但所有其他 16 列都不同,並且我想將所有資訊保留在一行中,最好在同一列中分號 ;作為它們之間的分隔符號。我想在輸出檔案中保留製表符作為分隔符號。非常感謝您的回答,如果您也能解釋我出錯的地方,那就更好了:)。

到目前為止我已經嘗試過:

awk -F'\t' 'NF>1{a[$1] = a[$1]";"$2}END{for(i in a){print i""a[i]}}' filename.txt

perl -F',' -anle 'next if /^$/;$h{$F[0]} = $h{$F[0]}.", ".$F[1];
END{print $_,$h{$_},"\n" for sort keys %h}' filename.txt

文件格式(其他 15 列與 B 列格式相同)

A     B     C    
123   fvv   ggg
123   kjf   ggg
123   ccd   att
567   abc   gst
567   abc   hgt
879   ttt   tyt

我想要的輸出(我需要所有 17 列,對於第 2-16 列,我需要與 B 列和 C 列相同的輸出)。 B 的所有情況都應在B 下,C 的所有情況應在C 下,D 的所有情況應在D 下,等等。 20.000 行,因為第一列有很多重複(對於這個特定檔案):

A     B                C
123   fvv;kjf;ccd      ggg;ggg;att
567   abc;abc          gst;hgt
879   ttt              lll

答案1

awk '{
      if(NR!=1){a[$1]=$2";"a[$1]}
      else print $0}
    END{
      n = asorti(a, b);
      for (n in b) {
      print b[n],a[b[n]]
      }
    }'

答案2

Perl 解決方案:

$ perl -F"\t" -anle 'if($.==1){print; next} push @{$k{$F[0]}},@F[1..$#F]; 
  END{print "$_\t" . join(";",@{$k{$_}}) for sort keys(%k)}' file 
A   B   
123 fvv;kjf;ccd
567 abc;abc
879 ttt

這可以適用於任意數量的欄位。但是,它確實需要將相當多的內容載入到記憶體中,如果您的檔案很大,這可能會成為問題。


至於你哪裡出錯了,我們無法告訴你,除非你解釋實際發生了什麼,但是,在我的腦海中,你的 perl 嘗試會失敗,因為:

  • 當您的輸入有製表符時,您正在使用-F,它將欄位分隔符號設為逗號。
  • 您正在使用-lprint "foo\n"。已經-l為每個列印呼叫添加了一個換行符,因此您將有多個空白行。
  • 您正在使用$h{$F[0]}.", ".$F[1];附加,因此第一次執行且未$h{$F[0]}定義時,您將,在儲存值的開頭新增額外的值。
  • 您只查看第二個字段,忽略所有其他字段。

同樣,你的意志awk也會失敗,因為:

  • 您正在列印foo""bar,這將連接輸出,每個欄位之間沒有空格。您想要print foo,bar並且也想要OFS="\t"製表符分隔的輸出。
  • 您只查看第二個字段,忽略所有其他字段。

答案3

為這一句抱歉,但事情是這樣的——

awk 'BEGIN{FS="\t"} {for(i=2; i<=NF; i++) { if (!a[$1]) a[$1]=$1FS$i ;else a[$1]=a[$1]";"$i};if ($1 != old) b[j++] = a[old];old=$1 } END{for (i=0; i<j; i++) print b[i] }' 1

123 fvv ;kjf;ccd
567 abc;abc
879 ttt

答案4

awk '
    function p(n,A){
        s = n
        for(i=2;i<=NF;i++){
            s = s "\t" A[i]
            A[i] = $i
        }
        if(n)
            print s
    }
    NR==1{
        print
        next
    }
    $1==n{
        for(i=2;i<=NR;i++)
            A[i] = A[i] ";" $i
        next
    }
    {
        p(n,A)
        n = $1
    }
    END{
        p(n,A)
    }
    ' file

相關內容