由線

2011-06-30 60 views
1

我只想重點線BASH從其減去文件從另一個一個。減去CSV-文件,但如果該行是相同的。而不是比較我想要查看的行是否在一個字段中匹配的行。由線

例如第一個文件

EMAIL;NAME;SALUTATION;ID 
[email protected];Foo;Mr;1 
[email protected];Bar;Ms;2 

第二個文件

EMAIL;NAME 
[email protected];Foo 

的resultfile應該

EMAIL;NAME;SALUTATION;ID 
[email protected];Bar;Ms;2 

我想你知道我在說什麼;)

怎麼可能在慶典?我很容易用Java來做這件事,但我真的很想學習如何在bash中做到這一點。我也可以通過比較使用行排序

#!/bin/bash  
echo "Substracting Files..." 

sort "/tmp/list1.csv" "/tmp/list2.csv" "/tmp/list2.csv" | uniq -u >> /tmp/subList.csv 

echo "Files successfully substracted." 

不過。減去行arn't相同元組。所以我必須比較線與鍵。

有什麼建議嗎?非常感謝..尼爾斯

回答

4

一個可能的解決方案來。我的腦海裏是這個(在bash工作):

grep -v -f <(cut -d ";" -f1 /tmp/list2.csv) /tmp/list1.csv 

表示:
cut -d ";" -f1 /tmp/list2.csv:提取第二個文件的第一列。
grep -f some_file:使用文件作爲模式源。
<(some_command):這是一個過程替換。它執行該命令並將輸出提供給一個命名管道,然後該管道可用作grep -f的文件輸入。
grep -v:只打印線不匹配的圖案(多個)。

+1

不錯,優雅的使用unix-foo,如果使用cut/grep將不需要使用awk(儘管awk可能會更快,但沒有硬性規則,結果讓我感到驚訝) – Marcin

+0

在控制檯中正常工作,但使用它在shell腳本中導致:/tmp/substract.sh:4:語法錯誤:「(」unexpected – Nils

+0

@Nils:你使用'#!/ bin/bash'還是'#!/ bin/sh'?後者因爲*進程替換*是一個'bash'功能。 – bmk

1

更新:該問題的解決方案,通過joinawk

join --header -1 1 -2 1 -t";" --nocheck-order -v 1 1.csv 2.csv | | awk 'NR==1 {print gensub(";[^;]\\+$","","g");next} 1'  

這些都是逆答案:

$ join -1 1 -2 1 -t";" --nocheck-order -o 1.1,1.2,1.3,1.4 1.csv 2.csv 
EMAIL;NAME;SALUTATION;ID 
[email protected];Foo;Mr;1 

join救援。

或打印的名稱字段不-o跳繩:

$ join -1 1 -2 1 -t";" --nocheck-order 1.csv 2.csv | awk 'BEGIN {FS=";" ; OFS=";"} {$NF=""; print }' 

(但它仍然打印加;後的最後一個字段

HTH

+2

是不是反了?你可以讓連接返回不能連接的行嗎? – sehe

+0

但如何避免雙字段(在你的情況下的名稱),對我來說有5個匹配的字段,它看起來像一個混亂的所有他們追加到行.. – Nils

+0

已更新的回答。 –