2015-03-02 101 views
0

我有两个TSV文件,我想根据第一列中的通用性合并它们。该列没有标题,但数据是每个公司的名称。将基于列的TSV合并到多行

我有一个接近我想要的awk代码。问题是,我想合并公司每一次提到的信息,而不仅仅是第一次。

items.tsv看起来是这样的:

IBM 0.0107 100.0% 
APPL 0.0457 98.0% 
GOOGL 0.0227 100.0% 
GOOGL 0.0197 100.0% 
GOOGL 0.0997 90.0% 
GOOGL 0.0397 10.0% 

vendors.tsv:

IBM Dec 2011 
APPL Jan 2014 
GOOGL June 2015 

随着我的代码,输出为:

IBM 0.0107 100.0% Dec 2011 
APPL 0.0457 98.0% Jan 2014 
GOOGL 0.0227 100.0% June 2015 

三线缺失!所需的输出是这样的:

IBM 0.0107 100.0% Dec 2011 
APPL 0.0457 98.0% Jan 2014 
GOOGL 0.0227 100.0% June 2015 
GOOGL 0.0197 100.0% June 2015 
GOOGL 0.0997 90.0% June 2015 
GOOGL 0.0397 10.0% June 2015 

这是我一直在使用的代码:

awk ' 
    BEGIN {FS=OFS="\t"} 
    NR==FNR {a[$1] = $2 FS $3; next} 
    $1 in a {print $1, a[$1], $2, $3} 
' items.tsv vendors.tsv 

行的顺序并不重要。数据由标签\ t分隔。我希望有人能帮助!

(请注意,awk的代码是相同的东西我一直在使用,输出由我打完了,所以\ t是一些地方定期空间等)

回答

1

的问题是只是顺序输入文件。通过NR == FNR成语,(通常)将第一个文件读入数组,然后为第二个文件中的每个记录输出一行,使用该数组与第一个文件中的信息“加入”。由于您将供应商文件作为第二个文件,因此读入了三条记录并写出了三条记录。

同样重要的是,第一个文件具有唯一的键作为数组索引。只能有一个a["GOOGL"],但通过切换输入文件的顺序,该问题也会消失。

$ cat vendors.tsv 
IBM Dec 2011 
APPL Jan 2014 
GOOGL June 2015 

$ cat item.tsv 
IBM 0.0107 100.0% 
APPL 0.0457 98.0% 
GOOGL 0.0227 100.0% 
GOOGL 0.0197 100.0% 
GOOGL 0.0997 90.0% 
GOOGL 0.0397 10.0% 

$ cat merge.awk 
BEGIN {FS=OFS="\t"} 
NR==FNR {a[$1] = $2 FS $3; next} 
$1 in a { print $1, $2, $3, a[$1] } 

$ awk -f merge.awk vendors.tsv item.tsv 
IBM 0.0107 100.0% Dec 2011 
APPL 0.0457 98.0% Jan 2014 
GOOGL 0.0227 100.0% June 2015 
GOOGL 0.0197 100.0% June 2015 
GOOGL 0.0997 90.0% June 2015 
GOOGL 0.0397 10.0% June 2015