2017-07-31 155 views
0

我想比較兩個文件,然後在匹配時返回其中一個文件列。我現在使用的代碼是排除不匹配的模式,只是打印出匹配的模式。我需要使用grep打印所有匹配和不匹配的結果。打印匹配和非匹配模式

文件1:

A,42.4,-72.2 
B,47.2,-75.9 
Z,38.3,-70.7 
C,41.7,-95.2 

文件2:

F 
A 
B 
Z 
C 
P 
E 

當前結果:

A,42.4,-72.2 
B,47.2,-75.9 
Z,38.3,-70.7 
C,41.7,-95.2 

預期結果:

F 
A,42.4,-72.2 
B,47.2,-75.9 
Z,38.3,-70.7 
C,41.7,-95.2 
P 
E 

bash代碼:

while IFS=',' read point lat lon; do 

check=`grep "${point} /home/aaron/file2 | awk '{print $1}'` 

echo "${check},${lat},${lon}" 

done < /home/aaron/file1 
+0

對於文件1中沒有第一列值的文件2中的某行應該發生什麼? –

回答

4

在awk中:

$ awk -F, 'NR==FNR{a[$1]=$0;next}{print ($1 in a?a[$1]:$1)}' file1 file2 
F 
A,42.4,-72.2 
B,47.2,-75.9 
Z,38.3,-70.7 
C,41.7,-95.2 
P 
E 

解釋:

$ awk -F, '     # field separator to , 
NR==FNR {     # file1 
    a[$1]=$0     # hash record to a, use field 1 as key 
    next 
} 
{ 
    print ($1 in a?a[$1]:$1) # print match if found, else nonmatch 
} 
' file1 file2 
2

若y OU不關心順序,有一個join二進制的GNU的coreutils,不只是你需要什麼:

$sort file1 > sortedFile1 
$sort file2 > sortedFile2 
$join -t, -a 2 sortedFile1 sortedFile2 
A,42.4,-72.2 
B,47.2,-75.9 
C,41.7,-95.2 
E 
F 
P 
Z,38.3,-70.7 

它依賴於文件進行排序,否則不會工作。

現在請你離開我的/home/

2

另一join基礎的解決方案維護秩序

f() { nl -nln -s, -w1 "$1" | sort -t, -k2; }; join -t, -j2 -a2 <(f file1) <(f file2) | 
sort -t, -k2 | 
cut -d, -f2 --complement 

F 
A,42.4,-72.2,2 
B,47.2,-75.9,3 
Z,38.3,-70.7,4 
C,41.7,-95.2,5 
P 
E 

不能擊敗awk解決方案,但利用基於裝飾,去除裝飾圖案UNIX工具鏈另一種選擇。

0

您當前的解決方案存在的問題:
1。您在grep "${point} /home/aaron/file2中缺少雙引號。
2。您應該從另一個文件開始打印該文件中的所有行

while IFS=',' read point; do 
    echo "${point}$(grep "${point}" /home/aaron/file1 | sed 's/[^,]*,/,/')" 
done < /home/aaron/file2 

3。 grep可以給出不止一個結果。你想要哪一個(head -1)?
的改善將是

while IFS=',' read point; do 
    echo "${point}$(grep "^${point}," /home/aaron/file1 | sed -n '1s/[^,]*,/,/p')" 
done < /home/aaron/file2 

4。使用while是錯誤的方法。
對於小文件,它將完成所做的工作,但是您會遇到更大的文件。原因是你會爲file2中的每一行調用grep,讀取file1很多次。
更好的是使用awk或其他解決方案。 另一種解決方案是使用sed與另一sed命令的輸出:

sed -r 's#([^,]*),(.*)#s/^\1$/\1,\2/#' /home/aaron/file1 

這會給命令用於第二sed

sed -f <(sed -r 's#([^,]*),(.*)#s/^\1$/\1,\2/#' /home/aaron/file1) /home/aaron/file2