Awk

刪除第一列重複的行

  • April 22, 2019

我有一個文件,其中字元串由特殊字元串(不是逗號或分隔符)分隔,例如<vvv>. 我想檢查第一個欄位中的所有字元串是否都是唯一的。如果發現同一欄位的重複行,我想刪除任何重複的行(保留第一次出現)。

例子:

aaa<vvv>bbb<vvv>ccc
xxx<vvv>yyy<vvv>zzz
aaa<vvv>new<vvv>new2
111<vvv>222<vvv>333

我想得到:

aaa<vvv>bbb<vvv>ccc
xxx<vvv>yyy<vvv>zzz
111<vvv>222<vvv>333

我們刪除aaa<vvv>new<vvv>new2是因為aaa已經出現了。

我不喜歡我們awk,除非它是唯一的解決方案。它的語法對我來說有點複雜,因為我不熟悉 Linux。

不用awk 太多

$ awk -v OFS="<" '{ print NR, $0 }' file | sort -t '<' -u -k2,2 | sort -t '<' -k1,1n | cut -d '<' -f 2-
aaa<vvv>bbb<vvv>ccc
xxx<vvv>yyy<vvv>zzz
111<vvv>222<vvv>333

這僅用於awk將行號插入<到原始數據中。我們這樣做是為了能夠跟踪原始行的順序。我們<用作行號和行其餘部分之間的分隔符,因為這也顯示為原始第一個欄位和行其餘部分之間的分隔符。

awk用於插入行號的管道的第一階段之後,數據將如下所示

1<aaa<vvv>bbb<vvv>ccc
2<xxx<vvv>yyy<vvv>zzz
3<aaa<vvv>new<vvv>new2
4<111<vvv>222<vvv>333

管道的下一步在第二個欄位(第一個原始欄位)上對其進行排序,刪除重複項。結果將是

4<111<vvv>222<vvv>333
1<aaa<vvv>bbb<vvv>ccc
2<xxx<vvv>yyy<vvv>zzz

第二個sort通過對第一個欄位上的行進行數字排序來恢復原始行順序,我們得到

1<aaa<vvv>bbb<vvv>ccc
2<xxx<vvv>yyy<vvv>zzz
4<111<vvv>222<vvv>333

然後cut從第一個欄位(和插入的分隔符)中刪除數字。


一個完全不使用就給出有序輸出的解決方案awk看起來像

$ sort -t '<' -u -k1,1 file
111<vvv>222<vvv>333
aaa<vvv>bbb<vvv>ccc
xxx<vvv>yyy<vvv>zzz

這本質上是上述管道中的第二步,它在第一個欄位上對文件進行排序,同時刪除重複項。


一個awk解決方案看起來像

$ awk -F '<' '!seen[$1]++' file
aaa<vvv>bbb<vvv>ccc
xxx<vvv>yyy<vvv>zzz
111<vvv>222<vvv>333

這會將第一個欄位作為鍵儲存在一個名為的關聯數組中seen,併後遞增關聯的值。如果給定鍵的數組中的值為零(即,以前沒有見過第一個欄位),則列印該行。

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