【问题标题】:Joining 2 files to 1 in shell [closed]在shell中将2个文件加入1个[关闭]
【发布时间】:2012-12-14 12:58:32
【问题描述】:

如何在shell中加入2个文件,例如:

文件1-

server1          monthly      25
server2          monthly      24
server3          daily        21
server4          weekly       7
server5          weekly       7                                         

文件2-

server1          monthly      5
server2          monthly      4
server3          daily        1
server4          weekly       2

你能帮我得到这样的输出吗:

server1          monthly      25     5
server2          monthly      24     4
server3          daily        21     1
server4          weekly       7      2
server5          weekly       7      0

【问题讨论】:

  • server1 每月 25 server2 每月 24 server3 每天 21 server4 每周 7 server5 每周 7 server1 每月 5 server2 每月 4 server3 每天 1 server4 每周 2 server1 每月 25 5 server2 每月 24 4 server3 每天 21 1 server4 每周 7 2 server5 每周 7 0

标签: linux file shell unix join


【解决方案1】:

这是join的工作:

$ join -a 1 -a 2 -e 0 -o '1.1 1.2 1.3 2.3' file1 file2
server1 monthly 25 5
server2 monthly 24 4
server3 daily 21 1
server4 weekly 7 2
server5 weekly 7 0

管道到column -t 以获得格式良好的表格:

$ join -a 1 -a 2 -e 0 -o '1.1 1.2 1.3 2.3' file file2 | column -t 
server1  monthly  25  5
server2  monthly  24  4
server3  daily    21  1
server4  weekly   7   2
server5  weekly   7   0

使用重定向操作符将其存储到一个新文件中:

$ join -a 1 -a 2 -e 0 -o '1.1 1.2 1.3 2.3' file file2 | column -t > newfile

解释:

-a            print unpairable lines from file FILENUM, where FILENUM is
              1 or 2, corresponding to FILE1 or FILE2

-e EMPTY      replace missing input fields with EMPTY

-o FORMAT     obey FORMAT while constructing output line

-a 用于在file1 中显示诸如server 5.. 之类的行,其中在file2 中找不到这样的行-e 0 将任何空字段替换为0-o 用于格式化输出其中1.1 表示file1 field 11.3 表示file1 field 3 等。

注意:join 确实需要先对文件进行排序(在这种情况下它们已经是)因此通常与sort 命令的使用结合使用。

【讨论】:

  • 这适用于示例数据,但我怀疑实际过程需要在字段 1 和 2 上加入。(“server1 每月”不应与“server1 每日”加入),所以进行一些预处理的输入将是使用 join 所必需的。
  • 我认为在这种情况下,示例数据是实际数据,for example 是我在编辑中添加的。如果确实是这种情况(我怀疑我们会知道),那么是的,需要进行一些预处理/后处理。
【解决方案2】:

这是使用awk的一种方式:

awk 'FNR==NR { a[$1,$2]=$3; next } { print $0, (a[$1,$2] ? a[$1,$2] : "0") | "column -t" }' file2 file1

结果:

server1  monthly  25  5
server2  monthly  24  4
server3  daily    21  1
server4  weekly   7   2
server5  weekly   7   0

解释:

FNR==NR { ... } 是一个仅适用于参数列表中的第一个文件的构造
因此,对于第一个文件,我们将第一列和第二列添加到数组中,将第三列分配为值。 'next' 只是强制 awk 读取下一行输入(因此,它会跳过处理其余代码)
一旦 awk 处理完第一个文件,它将移至第二个文件

awk 现在将打印出第二个文件中的每一行。在此打印语句的末尾附加了一个称为三元运算符的运算符,此语句的形式为: ( x ? a : b )
它的意思很简单:如果 (x) 则 (a) 否则 (b)。我本来可以写:

awk 'FNR==NR { a[$1,$2]=$3; next } { if (a[$1,$2]!=0) print $0, a[$1,$2]; else print $0, "0" }' file2 file1 | column -t

...但是三元组很性感。

【讨论】:

  • 非常感谢..Awk 对我来说效果很好..但我想了解这里的逻辑
  • @user1899817 awk 是一个很棒的工具,可以让你做一些强大的事情,但是 join 就是为此目的而编写的,你有 --helpman 页面供参考,绝对是适合工作的工具。
  • 非常感谢 Sudo_O -Join 很好解释,它也对我有帮助,但我仍然很想理解 awk 的逻辑
  • 感谢史蒂夫的解释
猜你喜欢
  • 2013-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-18
  • 2014-08-09
相关资源
最近更新 更多