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

Compare first column of one file with the first column of second and print associated column of each if there was a match

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

与此 Q 类似,但我想打印两个文件中的列,而不是一个文件:

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[]; next} () in a {print a[]}' File1.txt File2.txt

a[]不想打印

提前致谢。

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

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

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

这输出:

foo 1589.0
hi 33.7

解释:

  • 运行 对两个文件执行 comm 命令。
  • comm 的两个 "files" 实际上是进程替换的,所以它们首先排序(comm 期望排序输入)并且只显示第一列。
  • comm-1 -2 参数告诉它只打印文件中的共同元素(它可以显示第一个文件独有的元素、第二个文件独有的元素或两者共有的元素)
  • 一旦您获得了两个文件中的共同元素,for each 这些共同元素,继续使用 awk 对每个文件进行 grep 以查找它出现的行,并仅显示第二个值。

所以,最后,我们需要一个 bash for 循环,sortcommawk 多次。可能不是最优雅的解决方案,但它完成了工作。

能否请您尝试关注。

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

输出如下。

foo 1589.0
hi 33.7

您的尝试遇到的问题: 您在 FNR==NR 条件下的唯一表现是好的 a[]它没有任何价值,它只在数组 a 中创建了它的索引,所以这就是为什么在读取第二个 Input_file 时它无法打印任何内容的原因。

您要做的实际上是对存储在文本文件中的两个表进行内部联接,而 Linux 联接命令正是为此而设计的。

尝试:

join -t' ' -1 1 -2 1 -o 2.2,1.2 <(sort file1.txt) <(sort file2.txt) 
foo 1589.0
hi 33.7

解释:

  • 字段分隔符指定为-t。我假设您的数据在这些文本文件中由单个 space 分隔。
  • -1 1 -2 1表示在左侧文件的第一个字段和右侧文件的第一个字段上连接。
  • -o 2.2,1.2 定义了您想要 return 的字段。第二个文件的第二个字段,然后是第一个文件的第二个字段。
  • 最后,请注意我对输入文件进行了排序,因为文件需要按您打算加入的字段排序,Linux 加入才能正常工作。

另请参阅此博客 (ref)。

尝试 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