2017-07-15 54 views
0

我有文件,這看起來是這樣,(可以有更多的行或列):巴什 - 比較行然後打印只是原始行

dif-1-2-3-4.com 1 1 1 
dif-1-2-3-5.com 1 1 2 
dif-1-2-4-5.com 1 2 1 
dif-1-3-4-5.com 2 1 1 
dif-2-3-4-5.com 1 1 1 

而且我想這些數字比較:

1 1 1 
1 1 2 
1 2 1 
2 1 1 
1 1 1 

並打印那些不重複的行,所以我得到這樣的:

dif-1-2-3-4.com 1 1 1 
dif-1-2-3-5.com 1 1 2 
dif-1-2-4-5.com 1 2 1 
dif-1-3-4-5.com 2 1 1 
+0

你寫*可以有更多的列或行*。可以在那裏,比方說,與數字比較15個領域? – RomanPerekhrest

+1

允許排序,如'sort -k2 files | uniq -f1'? –

+0

是的,@RomanPerekhrest,可以有更多的領域進行比較,而不只是數字1或2. –

回答

4

另一種簡單的方法是用sortuniq使用KEYDEF用於與sort字段2-4和與uniq跳過字段1,例如

$ sort file.txt -k 2,4 | uniq -f1 

實施例使用/輸出

$ sort file.txt -k 2,4 | uniq -f1 
dif-1-2-3-4.com 1 1 1 
dif-1-2-3-5.com 1 1 2 
dif-1-2-4-5.com 1 2 1 
dif-1-3-4-5.com 2 1 1 
+1

如果'sort'版本支持'-u',也可以使用'sort -u -k 2,4 file.txt' – Sundeep

+0

是的,謝謝 - 這也節省了額外的子shell。 –

+0

如果這很重要,這將潛在地*丟失文件順序的任何含義。否則,很好的解決方案 – dawg

2

保持三元組的運行記錄已經看到和只打印他們第一次出現:

$ awk '!(($2,$3,$4) in seen) {print; seen[$2,$3,$4]}' file 
dif-1-2-3-4.com 1 1 1 
dif-1-2-3-5.com 1 1 2 
dif-1-2-4-5.com 1 2 1 
dif-1-3-4-5.com 2 1 1 
+0

很好的答案! '!'之後的括號是否必要? – archemiro

+1

是的,@archimiro,他們是必要的。由於'!'比'in'運算符具有更高的優先級,因此外部的parens是必需的。內部支撐是用逗號模擬多維數組的一部分。同樣可以寫成「!($ 2 SUBSEP $ 3 SUBSEP $ 4)」,在這種情況下只需要外部的零部件。有關詳細信息,請參閱https://www.gnu.org/software/gawk/manual/html_node/Multidimensional.html#Multidimensional和https://www.gnu.org/software/gawk/manual/html_node/Precedence.html。 – jas

+0

感謝您的解釋和參考:)。我問,因爲我刪除了外面的parens並得到了同樣的結果。這只是一種情況,它可以以任何方式工作? (我正在使用GNU Awk 4.1.4)。 – archemiro

1

這適用於POSIX和GNU AWK:

$ awk '{s="" 
     for (i=2;i<=NF; i++) 
       s=s $i "|"} 
     s in seen { next } 
     ++seen[s]' file 

這可以縮短爲:

$ awk '{s=""; for (i=2;i<=NF; i++) s=s $i "|"} !seen[s]++' file 

還支持可變數量的列。

如果你想要一個sortuniq解決方案,也尊重文件順序(即打印的第一套重複打印,而不是後者),你需要做一個裝飾,排序,未整理的方法。

您可以:

  1. 使用cat -n裝飾行號文件;
  2. sort -k3 -k1n首先在所有的字段上排序,從3開始,然後在行的末尾加上數字;
  3. add -u如果您的版本sort支持該選項或使用uniq -f3僅保留dups組中的第一個;
  4. 最後用sed -e 's/^[[:space:]]*[0-9]*[[:space:]]*//刪除添加的行號:

    cat -n file | sort -k3 -k1n | uniq -f3 | sed -e 's/^[[:space:]]*[0-9]*[[:space:]]*//'

AWK是在這種情況下,更容易和更快。

2

嘗試,以下awk代碼太:

awk '!a[$2,$3,$4]++' Input_file 

說明: 創建名爲a的陣列其指數爲$2,$3,$4。所述條件這裏是!a,(這意味着任何線的$2,$3,$4不存在於陣列a),然後做兩兩件事:

  1. 增加該特定索引的值,以,使得下一次條件將對於相同的$2,$3,$4索引,在數組a中不成立。
  2. 不指定一個動作,(所以awk作品中的條件模式,然後動作),所以默認動作將是打印當前行。這將繼續執行Input_file中的所有行,並且最後一行將不會打印,因爲其$2,$3,$4已存在於數組a中。

我希望這有助於。

+1

Neato,但解釋仍然需要... – agc

+0

感謝agc對它進行編輯,現在看起來更整齊:) – RavinderSingh13