我该怎么做?
File1 看起来像这样:
foo 1 scaf 3
bar 2 scaf 3.3
File2 看起来像这样:
foo 1 scaf 4.5
foo 1 boo 2.3
bar 2 scaf 1.00
我想做的是找到同时出现在 File1 和 File2 中的行 当字段 1、2 和 3 相同时。
有办法吗?
最佳答案
这是正确的答案(就使用标准 GNU coreutils 工具而言,而不是在您指定的 perl/awk 中编写自定义脚本它)。
$ join -j1 -o1.2,1.3,1.4,1.5,2.5 <(<file1 awk '{print $1"-"$2"-"$3" "$0}' | sort -k1,1) <(<file2 awk '{print $1"-"$2"-"$3" "$0}' | sort -k1,1)
bar 2 scaf 3.3 1.00
foo 1 scaf 3 4.5
好的,它是如何工作的:
首先,我们将使用一个很棒的工具
join
可以合并两行。join
有两个要求:- 我们只能通过一个字段加入。
- 两个文件都必须按关键字列排序!
我们需要在输入文件中生成 key ,为此我们使用一个简单的
awk
。脚本:$ cat file1 foo 1 scaf 3 bar 2 scaf 3.3 $ <file1 awk '{print $1"-"$2"-"$3" "$0}' foo-1-scaf foo 1 scaf 3 bar-2-scaf bar 2 scaf 3.3
你看,我们在第一列添加了一些键,例如“foo-1-scaf”。 我们对 file2 做同样的事情。 顺便提一句。
<file awk
, 只是花哨的写作方式awk file
, 或cat file | awk
.我们还应该按键排序我们的文件,在我们的例子中这是第 1 列,所以我们添加 到命令的末尾
| sort -k1,1
(排序从第 1 列到第 1 列的文本)此时我们可以生成文件 file1.with.key 和 file2.with.key 并加入它们, 但是假设这些文件很大,我们不想通过文件系统复制它们。相反,我们可以使用名为
bash
的东西process substitution将输出生成到命名管道(这将避免任何 不必要的中间文件创建)。有关详细信息,请阅读提供的链接。我们的目标语法是:
join <( some command ) <(some other command)
最后一件事是解释花式连接参数:
-j1 -o1.2,1.3,1.4,1.5,2.5
-
-j1
- 在第一列中按键加入(在两个文件中) -o
- 只输出那些字段1.2
(第一个文件字段 2),1.3
(第一个文件第 3 列)等这样我们就加入了行,但是
join
仅输出必要的列。
-
从这篇文章中吸取的教训应该是:
- 您应该掌握 coreutils 包,这些工具组合起来非常强大,您几乎永远不需要编写自定义程序来处理这种情况,
- 核心实用工具也非常快速且经过严格测试,因此它们始终是最佳选择。
关于linux - 在 Unix 上连接文本文件中的多个字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2619562/