将一个文件的第一列与第二个文件的第一列进行比较,如果匹配则打印每个文件的相关列
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
循环,sort
,comm
和 awk
多次。可能不是最优雅的解决方案,但它完成了工作。
能否请您尝试关注。
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
我有两个文件,我需要比较它们的第一列,如果找到匹配项,我想从两个文件中输出相应的值。
与此 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
循环,sort
,comm
和 awk
多次。可能不是最优雅的解决方案,但它完成了工作。
能否请您尝试关注。
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