2017-07-31 153 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