2017-03-06 103 views
2

我無法找到真正從另一個文件中減去一個文件的答案。從另一個文件中減去一個文件中的行

我的目標是刪除一個文件中發生在另一個文件中的行。 應該尊重多個事件,這意味着例如如果一行在文件A中出現4次並且在文件B中只出現一次,則文件C應該具有這些行中的3行。

文件:

1 
3 
3 
3 
4 
4 

文件B:

1 
3 
4 

文件C(所希望的輸出)

3 
3 
4 

預先感謝

+0

使用Perl。將文件B加載到哈希值中,其中value =每個值的出現次數。對於文件A的每一行,如果找到一個非零值,則遞減該值。如果找不到,則發出該線。 – Ben

+0

到目前爲止您嘗試過什麼?你生成的任何代碼?任何錯誤消息? –

+0

@JoseRicardoBustosM。我嘗試將文件B中的所有條目添加到數組中,並刪除文件A中的數組元素,但不幸的是,這種方式在AWK中不起作用。詹姆斯布朗的答案似乎運作良好,雖然 – Hawk

回答

3

在awk中:

$ awk 'NR==FNR{a[$0]--;next} ($0 in a) && ++a[$0] > 0' f2 f1 
3 
3 
4 

解釋:

NR==FNR {     # for each record in the first file 
    a[$0]--;    # for each identical value, decrement a[value] (of 0) 
    next 
} 
($0 in a) && ++a[$0] > 0' # if record in a, increment a[value] 
          # once over remove count in first file, output 

如果你要打印物品i ñf1不在f2你可以失去($0 in a) &&

$ echo 5 >> f1 
$ awk 'NR==FNR{a[$0]--;next} (++a[$0] > 0)' f2 f1 
3 
3 
4 
5 
+1

如果我正確地理解了這個問題,如果'3'在'f2'中出現了兩次,在'f1'中出現了三次,那麼它只能在輸出中出現一次。在這個解決方案中它仍然會出現兩次。 – jas

+1

@jas在OP文件C - 期望的輸出中,3出現兩次。 –

+1

正確,@GeorgeVasiliou,但我的意思是一個不同的測試用例,其中文件B包含'1 3 3 4'。 (在這種情況下,例如,Sundeep的解決方案輸出只是'3 4'。) – jas

1

如果輸入文件已經按示例中所示進行排序,comm會更適合從手冊頁

$ comm -23 f1 f2 
3 
3 
4 

選項說明:

-2  suppress column 2 (lines unique to FILE2) 
    -3  suppress column 3 (lines that appear in both files) 
1

你可以這樣做:

awk 'NR==FNR{++cnt[$1] 
      next} 
    cnt[$1]-->0{next} 
    1' f2 f1 
相關問題