Linux

按重複對列進行排序並保留第一次出現

  • September 5, 2021

我有一個文件如下

1:A
2:B
3:A

我需要輸出為:

1:A
2:B

由於第三個條目第二列包含 A,就像第一個條目一樣,它會刪除它。它還需要區分大小寫。

這是一個非常大的文件,所以節省時間會很好。

我已經嘗試過了,但它似乎只列印了獨特的線條

sort -u -t':' -k3,3 file

使用sort

正如 Ed 在他的評論中所說,您的sort命令正在對第三個欄位進行排序,而實際上您只有兩個欄位(:欄位分隔符)。因此,要修復它,請替換32for 鍵。

但是,當記錄按其鍵值而不是按行/記錄號排序時,源文件中的原始記錄順序就會混亂:

$ sort -u -t':' -k2,2 test.txt 
1:A
2:B
6:C
5:a
4:b
$

這可能不是你想要的。然而,這很容易通過sort再次管道輸出來解決:

$ sort -u -t':' -k2,2 test.txt | sort 
1:A
2:B
4:b
5:a
6:C
$

注意:正如您所說的那樣,您有一個大文件,為了加快速度,您可能需要考慮使用--parallel標誌1:

sort --parallel=<n> -u -t':' -k2,2 test.txt | sort --parallel=<n>

<n>您可用的核心數量是什麼時候。

使用awk

如果原始數據位於名為 的文件中,則擴展您的範例文件test.txt,如下所示:

1:A
2:B
3:A
4:b
5:a
6:C

並且,再次將:視為欄位分隔符,然後您可以使用awk2。

例如這一行:

awk 'BEGIN{FS=":"}{if (!seen[$2]++)print $0}' test.txt

給出以下結果:

$ awk 'BEGIN{FS=":"}{if (!seen[$2]++)print $0}' test.txt 
1:A
2:B
4:b
5:a
6:C
$

您可以通過查看邏輯來了解其工作原理,使用

$ awk 'BEGIN{FS=":"}{print !seen[$2]++}' test.txt 
1
1
0
1
1
1
$
  • 首先,欄位分隔符用 指定FS=":"
  • 其次,否定運算符為尚未看到的第二個欄位條目提供“真實”結果。
  • 最後,print $0列印整個記錄,即目前行。

將其放入 shell 腳本3而不是awk腳本會給出:

#!/bin/sh

awk -F':' '
 (!seen[$2]++) {
   print $0
 }
' "$1"

參考資料

1如何對大文件進行排序

2根據三列中的 2 列的資訊保持唯一行答案

3這個在 awk 腳本頭中指定其他標誌的答案

引用自:https://unix.stackexchange.com/questions/667694