我正在尋找從以下格式的文件中獲取的命令:
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
更多選項:
perl
,如果您不關心行的順序。perl -lane '$k{$F[0]}=$F[1]; END{print "$_ $k{$_}" for keys(%k)}' file
一個更簡單的
awk
awk '{c[$1]=$0;} END{for(i in c){print c[i]}}' file
一個愚蠢的貝殼
while read a b; do grep -w ^"$a" file | tail -n1 ; done < file | uniq