将一个文件的第一列与第二个文件的第一列进行比较,如果存在匹配项,则打印每个文件的关联列

时间:2018-11-13 02:04:47

标签: bash awk sysadmin

我有两个文件,我需要比较它们的第一列,如果找到匹配项,我想从两个文件中输出相应的值。

类似于此Q,但我想从两个文件中打印列中的一个而不是:How to compare multiple columns in two files and retrieve the corresponding value from another column if match found

File1.txt

adeqY   33.7
AIsLX   65.6
AmuBv   1589.0
aZMIx   84.4

File2.txt

AmuBv foo
iwwlp bar
adeqY hi
qUbJZ bye

输出

hi 33.7
foo 1589.0

我有以下awk命令,但我只设法从File2打印出第二列匹配项:

awk 'FNR==NR{a[$1]; next} ($1) in a {print $2 a[$2]}' File1.txt File2.txt

a[$2]不想打印

谢谢。

4 个答案:

答案 0 :(得分:1)

请您尝试以下。

   label    count                                                               
0    0.0  7128722
1    1.0    29024

输出如下。

awk 'FNR==NR{a[$1]=$2;next} ($1 in a){print $2,a[$1]}' Input_file1  Input_file2

您尝试遇到的问题: :您在foo 1589.0 hi 33.7 上做的只有一件事情,前提是您的FNR==NR没有任何价值,只是创建了在数组a[$1]中建立索引,这就是为什么在读取第二个Input_file时它无法打印任何内容的原因。

答案 1 :(得分:1)

您想要做的实际上是在存储在文本文件中的两个表上有一个INNER JOIN,而Linux join命令就是为此而设计的。

尝试:

.blue

说明:

  • 字段分隔符指定为-t。我假设您的数据在这些文本文件中用单个空格分隔。
  • 据说join -t' ' -1 1 -2 1 -o 2.2,1.2 <(sort file1.txt) <(sort file2.txt) foo 1589.0 hi 33.7 在左侧文件的第一个字段和右侧文件的第一个字段上联接。
  • -1 1 -2 1定义您要返回的字段。第二个文件中的第二个字段,然后是第一个文件中的第二个字段。
  • 最后,请注意,我对输入文件进行了排序,因为文件需要按您打算通过其加入的字段进行排序,以使Linux连接正常工作。

另请参见此博客(ref)。

答案 2 :(得分:0)

这里发生的是,一旦您在最后一个awk语句中打印结果,a[]数组就不再在范围内,因此为什么第二个值不打印。

也许还有另一种方法awk,但这是我想出的解决方案:

for each in $(comm -1 -2 <(awk '{print $1 }' file1.txt | sort ) <(awk '{print $1 }' file2.txt | sort) ); do echo $(grep $each file2.txt | awk '{print $2}') $(grep $each file1.txt | awk '{print $2}') ; done;

这将输出:

foo 1589.0
hi 33.7

说明:

  • 在两个文件上运行comm命令。
  • 赋予comm的两个“文件”实际上是过程替换的,因此它们首先被排序(comm需要排序的输入),并且仅显示第一列。
  • -1 -2的{​​{1}}参数告诉它仅打印文件中的公共元素(它可以显示第一个文件所独有的元素,第二个文件所独有的元素,或两个文件都具有的共同元素)
  • 一旦您拥有两个文件(comm)中的公共元素,请继续并针对出现的行对每个文件进行grep操作,并使用awk仅显示第二个值。

因此,最后,我们需要bash for each循环,forsortcomm多次。可能不是最优雅的解决方案,但可以完成工作。

答案 3 :(得分:0)

尝试Perl变体

$ cat eskp1.txt
adeqY   33.7
AIsLX   65.6
AmuBv   1589.0
aZMIx   84.4

$ cat eskp2.txt
AmuBv foo
iwwlp bar
adeqY hi
qUbJZ bye

$ perl -F"\s+" -lane 'BEGIN { %kv=map{split /\s+/ } qx(cat eskp1.txt) } { print "$F[1] $kv{$F[0]}" if $kv{$F[0]} } ' eskp2.txt
foo 1589.0
hi 33.7