打印匹配和非匹配模式

时间:2017-07-31 13:41:44

标签: regex bash unix awk grep

我正在尝试比较两个文件,然后在匹配时返回一个文件列。我现在使用的代码是排除不匹配的模式,只打印出匹配的模式。我需要使用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

4 个答案:

答案 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