我正在尝试比较两个文件,然后在匹配时返回一个文件列。我现在使用的代码是排除不匹配的模式,只打印出匹配的模式。我需要使用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 :(得分: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
答案 1 :(得分:2)
如果您不关心订单,那么GNU coreutils中的join
二进制文件可以满足您的需求:
$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 :(得分: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
解决方案,而是使用基于decorate-undecorate模式的unix工具链的另一种替代方案。
答案 3 :(得分: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