分組 uniq 指令?

分組 uniq 指令?

我正在尋找從以下格式的文件中獲取的命令:

hello 32
hello 67
hi    2
ho    1212
ho    1390
ho    3000

採用這種格式(透過取得「群組」的最後一行來消除重複):

hello 67
hi    2
ho    3000

目前我正在使用 Python 和 pandas 片段:

    df = pd.read_csv(self.input().path, sep='\t', names=('id', 'val'))

    # how to replace this logic with shell commands?
    surface = df.drop_duplicates(cols=('id'), take_last=True)

    with self.output().open('w') as output:
        surface.to_csv(output, sep='\t', cols=('id', 'val'))

更新:感謝您的精彩回答。以下是一些基準:

輸入檔大小為 246M,包含 8583313 行。順序並不重要。第一列的固定大小為 9 個字元。

輸入檔案範例:

000000027       20131017023259.0        00
000000027       20131017023259.0        11
000000035       20130827104320.0        01
000000035       20130827104320.0        04
000000043       20120127083412.0        01
...

                              time        space complexity

tac .. | sort -k1,1 -u        27.43682s   O(log(n))
Python/Pandas                 11.76063s   O(n)
awk '{c[$1]=$0;} END{for(...  11.72060s   O(n)

由於第一列有固定長度,uniq -w也可以使用:

tac {input} | uniq -w 9        3.25484s   O(1)

答案1

這看起來很瘋狂,希望有更好的方法,但:

tac foo | sort -k 1,1 -u

tac用於反轉文件,因此您得到的是最後一個而不是第一個。

-k 1,1說僅使用第一個字段進行比較。

-u使其獨一無二。

答案2

如果您不介意輸出順序,這裡有一個awk解決方案:

$ awk '
    {a[$1] = !a[$1] ? $2 : a[$1] < $2 ? $2 : a[$1]}
    END {
        for (i in a) { print i,a[i] }
    }
' file
hi 2
hello 67
ho 3000

答案3

更多選項:

  1. perl,如果您不關心行的順序。

    perl -lane '$k{$F[0]}=$F[1]; END{print "$_ $k{$_}" for keys(%k)}' file
    
  2. 一個更簡單的awk

    awk '{c[$1]=$0;} END{for(i in c){print c[i]}}' file
    
  3. 一個愚蠢的貝殼

    while read a b; do grep -w ^"$a" file | tail -n1 ; done < file | uniq
    

答案4

那你可以這樣做sort

sort -u -k1,1 test

編輯:tac 是解決方案

相關內容