2017-08-02 84 views
1

下面存在是我的文件1項內容:比較COLUMN1,輸出{列1文件1}不會在文件2

123|yid|def| 
456|kks|jkl| 
789|mno|vsasd| 

,這是我的文件2內容

123|abc|def| 
456|ghi|jkl| 
789|mno|pqr| 
134|rst|uvw| 

我想在基於文件2文件1進行比較的唯一的事情是第1列。根據上述文件,則輸出只能輸出:

134|rst|uvw| 

行與行比較不是答案,因爲第2列和第3列都包含不同的內容,但只有第1列包含兩個文件中完全相同的內容。

我該如何做到這一點?

目前我在我的代碼中使用這樣的:

#sort FILEs first before comparing 

sort $FILE_1 > $FILE_1_sorted 
sort $FILE_2 > $FILE_2_sorted 

for oid in $(cat $FILE_1_sorted |awk -F"|" '{print $1}'); 
do 
echo "output oid $oid" 

#for every oid in FILE 1, compare it with oid FILE 2 and output the difference 

grep -v diff "^${oid}|" $FILE_1 $FILE_2 | grep \< | cut -d \ -f 2 > $FILE_1_tmp 
+0

給定文件1和文件2,你只想輸出'134 | rst | uvw |'?那麼爲什麼不進行基於行的比較工作?如果要合併具有文件1和文件2中匹配列1的行,可以使用'join -t'|' file1 file2',然後使用'cut'來只輸出相關的列。 – rubystallion

+0

我的輸入文件包含數千行,不可能知道要刪除哪行 – MFAY

回答

4

可以在Awk做到這一點很容易!

awk 'BEGIN{FS=OFS="|"}FNR==NR{unique[$1]; next}!($1 in unique)' file1 file2 

Awk作品通過一次處理輸入線一個。並且有Awk提供的特殊子句,BEGIN{}END{},它包含了在文件處理之前和之後運行的動作。

因此部分是在文件處理髮生之前設置的,而FSOFSAwk中的特殊變量,它們代表輸入和輸出字段分隔符。既然你提供的由|是去限制一個文件,你需要通過設置FS="|"也與|打印回解析它,所以設置OFS="|"

命令的主要部分來自後BEGIN條款,部分FNR==NR是爲了處理命令中提供的第一個文件參數,因爲FNR跟蹤兩個文件合併的行號和NR僅當前文件。因此,對於在所述第一文件中的每個$1,值被散列到稱爲unique然後當文件處理髮生時,部分!($1 in unique)將下降在第二個文件中,其$1值不是int散列陣列的那些行的陣列。

+1

+1 Nice!我認爲你的意思是「** ...所以在上面設置了'OFS =」|「'... **」。我試圖修復它,但我不允許編輯少於6個字符,很奇怪。 – Anubis

+0

感謝您的幫助。我完全理解了解釋,但是我錯過了什麼?我在測試命令時不斷收到語法錯誤。我做了一些研究,但發現語法已經正確 – MFAY

+0

@MAY:你是否正在運行命令?你有什麼版本的Awk? – Inian

1

下面是一個使用joinsortgrep

join -t"|" -j 1 -a 2 <(sort -t"|" -k1,1 file1) <(sort -t"|" -k1,1 file2) |\ 
    grep -E -v '.*\|.*\|.*\|.*\|' 

join在這裏所做的兩件事情的另一個一行。它將兩個文件中的所有行與匹配的鍵匹配,並使用-a 2選項還打印file2中不匹配的行。

由於join需要對輸入文件進行排序,我們對它們進行排序。

最後,grep刪除輸出中包含多於三個字段的所有行。