【问题标题】:Using UNIX join command to merge two files使用 UNIX join 命令合并两个文件
【发布时间】:2014-09-14 09:12:40
【问题描述】:

我正在尝试合并多个具有与以下示例类似的语法的文件。目前,我一直在试验两个文件。这些文件将始终具有相同的行数、相同的日期、相同的时间,并以相同的顺序排序。唯一的区别应该在值字段中。

文件1.csv

date,time,value,status  
2014/09/10,22:47:25,-0.0000000003542,9  
2014/09/10,23:14:25,-0.0000000002892,9  
2014/09/10,23:23:46,0.0000000005406,9  
2014/09/10,23:41:48,-0.0000000000142,9  
2014/09/11,00:18:40,-0.0000000009977,9  

文件2.csv

date,time,value,status  
2014/09/10,22:47:25,0.0000000725578,9  
2014/09/10,23:14:25,-0.0000000283722,9  
2014/09/10,23:23:46,-0.0000000368988,9  
2014/09/10,23:41:48,-0.0000000675033,9  
2014/09/11,00:18:40,-0.0000000774759,9  

期望的输出

date,time,value,value  
2014/09/10,22:47:25,-0.0000000003542,0.0000000725578
2014/09/10,23:14:25,-0.0000000002892,-0.0000000283722
2014/09/10,23:23:46,0.0000000005406,-0.0000000368988
2014/09/10,23:41:48,-0.0000000000142,-0.0000000675033
2014/09/11,00:18:40,-0.0000000009977,-0.0000000774759

我对在合并结果中保留状态值不感兴趣。我已经尝试了 join 命令的多种变体,最新的是:

join -t, -a 1 -a 2 -o 1.1 1.2 1.3 2.3 File1.csv File2.csv

不幸的是,我不断得到类似于下面的输出,它根本没有显示来自 File1.csv 的数据。

电流输出

date,time,value,value  
,,,0.0000000725578  
,,,-0.0000000283722  
,,,-0.0000000368988  
,,,-0.0000000675033  
,,,-0.0000000774759  
,,,0.0000001042118  

有人有什么建议吗?

谢谢。


更新

作为对此的跟进,我返回并更新了输入文件以将日期和时间合并到如下所示的单个字段中。

文件1.csv

日期时间、价值、状态
2014/09/10 22:47:25,-0.0000000003542,9
2014/09/10 23:14:25,-0.0000000002892,9
2014/09/10 23:23:46,0.0000000005406,9
2014/09/10 23:41:48,-0.0000000000142,9
2014/09/11 00:18:40,-0.0000000009977,9

文件2.csv

日期时间、价值、状态
2014/09/10 22:47:25,0.0000000725578,9
2014/09/10 23:14:25,-0.0000000283722,9
2014/09/10 23:23:46,-0.0000000368988,9
2014/09/10 23:41:48,-0.0000000675033,9
2014/09/11 00:18:40,-0.0000000774759,9

因此,我已将 join 命令更新为如下所示:

加入 -t, -a 1 -a 2 -o "1.1 1.2 2.2" File1.csv File2.csv

不幸的是,我仍然得到一个似乎省略了 File1.csv 内容的输出。

电流输出

日期时间、价值、价值
,,0.0000000725578
,,-0.0000000283722
,,-0.0000000368988
,,-0.0000000675033
,,-0.0000000774759


更新

问题似乎与每个文件的标题有关。如果我从文件中删除标题,然后尝试以下连接字符串:

加入 -t, -a 1 -a 2 -o "1.1 1.2 2.2" File1.csv File2.csv

它给出了以下所需的输出:

2014/09/10 22:47:25,-0.0000000003542,0.0000000725578
2014/09/10 23:14:25,-0.0000000002892,-0.0000000283722
2014/09/10 23:23:46,0.0000000005406,-0.0000000368988
2014/09/10 23:41:48,-0.0000000000142,-0.0000000675033
2014/09/11 00:18:40,-0.0000000009977,-0.0000000774759

有人知道让join忽略输入文件标题的方法吗?

谢谢,

【问题讨论】:

  • 似乎你最好在脚本中这样做,这样你就可以检查前三列是否确实相等,然后加入。
  • join 只能加入一个字段,默认为第一个字段。您有多行具有相同的日期,所以这不起作用。

标签: unix join


【解决方案1】:

awk 单行,无需测试:

awk -F, -v OFS="," '{k=$1 FS $2}NR==FNR{a[k]=$3;next}
                                k in a{print k,a[k],$3}' file1 file2

【讨论】:

  • 不幸的是,我在尝试时得到以下信息。 awk:第 1 行附近的语法错误
  • @TrinityEllis 我刚刚用上面的单线做了一个测试,它给出了完全预期的输出。
  • 嗯。您的一个衬里中的“}”和“k”之间的分隔符是什么?上面的图像对我来说出现在两行。当我尝试以空格作为分隔符的单行运行时,我得到了 awk 语法错误。
  • @TrinityEllis } 和 k 之间没有分隔符,您也可以将其设为空格。它是用 gnu awk 测试的。
  • 我正在运行 SunOS 5.10,所以我很好奇 awk 解释同一语句的方式是否会有所不同。
【解决方案2】:

您需要将所有输出字段规范放在一个参数中,因此您必须引用它:

join -t, -a 1 -a 2 -o "1.1 1.2 1.3 2.3" File1.csv File2.csv

但是,这不会产生您想要的输出。 join 连接单个键字段,默认为第一个字段。由于您在多行中有相同的日期,因此这些都连接在一起,结果是:

date,time,value,value
2014/09/10,22:47:25,-0.0000000003542,0.0000000725578
2014/09/10,22:47:25,-0.0000000003542,-0.0000000283722
2014/09/10,22:47:25,-0.0000000003542,-0.0000000368988
2014/09/10,22:47:25,-0.0000000003542,-0.0000000675033
2014/09/10,23:14:25,-0.0000000002892,0.0000000725578
2014/09/10,23:14:25,-0.0000000002892,-0.0000000283722
2014/09/10,23:14:25,-0.0000000002892,-0.0000000368988
2014/09/10,23:14:25,-0.0000000002892,-0.0000000675033
2014/09/10,23:23:46,0.0000000005406,0.0000000725578
2014/09/10,23:23:46,0.0000000005406,-0.0000000283722
2014/09/10,23:23:46,0.0000000005406,-0.0000000368988
2014/09/10,23:23:46,0.0000000005406,-0.0000000675033
2014/09/10,23:41:48,-0.0000000000142,0.0000000725578
2014/09/10,23:41:48,-0.0000000000142,-0.0000000283722
2014/09/10,23:41:48,-0.0000000000142,-0.0000000368988
2014/09/10,23:41:48,-0.0000000000142,-0.0000000675033
2014/09/11,00:18:40,-0.0000000009977,-0.0000000774759

相反,您可以加入 time 字段:

join -1 2 -2 2 -t, -a 1 -a 2 -o "1.1 1.2 1.3 2.3" File1.csv File2.csv

这是可行的,因为它需要对行进行排序。因此,如果有重复的时间,它将是乱序的,并且不会与前一天的行匹配。

【讨论】:

  • 谢谢。我正在考虑将日期和时间合并到一个字段值中,但在弄清楚连接之后我打算这样做。似乎我现在也应该考虑这个选项,我相信我可以用 sed 来做。
  • 嗯。当我尝试基于时间字段的连接时,我仍然得到与上面相同的输出。
猜你喜欢
  • 1970-01-01
  • 2016-06-20
  • 2015-05-10
  • 2012-12-17
  • 2020-08-20
  • 2012-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多