linux - 在 Unix 上连接文本文件中的多个字段

标签 linux bash unix join

我该怎么做?

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

我想做的是找到同时出现在 File1File2 中的行 当字段 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

好的,它是如何工作的:

  1. 首先,我们将使用一个很棒的工具 join可以合并两行。 join有两个要求:

    • 我们只能通过一个字段加入
    • 两个文件都必须按关键字列排序!
  2. 我们需要在输入文件中生成 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 列的文本)

  3. 此时我们可以生成文件 file1.with.keyfile2.with.key 并加入它们, 但是假设这些文件很大,我们不想通过文件系统复制它们。相反,我们可以使用名为 bash 的东西process substitution将输出生成到命名管道(这将避免任何 不必要的中间文件创建)。有关详细信息,请阅读提供的链接。

    我们的目标语法是:join <( some command ) <(some other command)

  4. 最后一件事是解释花式连接参数:-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/

相关文章:

linux - 使用 bash 脚本从文件中读取元素

java - 当我们执行 "kill -3 <pid>"时,输出文件会去哪里

linux - bash 中的日历计算

linux - ssh 使用私钥无需密码

linux - 第三个远程服务器中的 Bash 变量

regex - grep : Regex for IP doesnt match

java - 无法将 StAX 输入转换为 DOM DocumentFragment

linux - 以 headless 模式将 libreoffice 电子表格合并到多页文档中?

bash - ksh 和 bash 脚本之间的区别

linux - 无法打印进程的PID