【问题标题】:merge two csv files according to matching rows and add new columns in linux根据匹配的行合并两个csv文件并在linux中添加新列
【发布时间】:2015-01-30 22:57:45
【问题描述】:

我正在使用 java 开发一个应用程序,但为此我需要一个 csv 文件。我不太了解linux,但想知道是否有某种方法可以合并所需格式的csv文件。

我有两个包含数十万条记录的 csv 文件。示例如下:

name,Direction,Date
abc,sent,Jan 21 2014 02:06 
xyz,sent,Nov 21 2014 01:09
pqr,sent,Oct 21 2014 03:06  

和

name,Direction,Date
abc,received,Jan 22 2014 02:06
xyz,received,Nov 22 2014 02:06

所以,第二个 csv 文件将包含文件 1 的一些记录。我需要的是一个像这样的新 csv:

name,Direction,Date,currentDirection,receivedDate
abc,sent,Jan 21 2014 02:06,received,Jan 22 2014 02:06
xyz,sent,Nov 21 2014 01:09,received,Nov 22 2014 02:06
pqr,sent,Oct 21 2014 03:06

需要根据 column1 中的匹配数据添加列(第 4 列和第 5 列)。如果第二个文件中没有匹配的数据,则列应该像上面一样为空。

那么 linux 中有没有 bash 命令来实现这一点?

【问题讨论】:

    标签: linux unix


    【解决方案1】:

    awk 可能对你有用:

    kent$  awk -F, -v OFS="," 
           'BEGIN{print "name,Direction,Date,currentDirection,receivedDate"}
            NR==FNR&&NR>1{a[$1]=$0;next}
            FNR>1{printf "%s%s\n",$0,($1 in a?FS a[$1]:"")}' 2.csv 1.csv
    name,Direction,Date,currentDirection,receivedDate
    abc,sent,Jan 21 2014 02:06,abc,received,Jan 22 2014 02:06
    xyz,sent,Nov 21 2014 01:09,xyz,received,Nov 22 2014 02:06
    pqr,sent,Oct 21 2014 03:06
    

    更新

    kent$  awk -F, -v OFS="," 'BEGIN{print "name,Direction,Date,currentDirection,receivedDate"}
            NR==FNR&&NR>1{a[$1]=$2 FS $3;next}
            FNR>1{printf "%s%s\n",$0,($1 in a?FS a[$1]:"")}' 2.csv 1.csv 
    name,Direction,Date,currentDirection,receivedDate
    abc,sent,Jan 21 2014 02:06,received,Jan 22 2014 02:06
    xyz,sent,Nov 21 2014 01:09,received,Nov 22 2014 02:06
    pqr,sent,Oct 21 2014 03:06
    

    【讨论】:

    • kent - 它没有按预期工作。输出如下:name,Direction,Date,currentDirection,receivedDate abc,sent,Jan 21 2014 02:06 ,abc,received,Jan 22 2014 02:06
    • 第一列重复,列也没有按要求的格式排列。
    • @user3884944 它在这里与您的测试文件一起工作(如答案所示)。也许你有不同的 awk 版本?
    • 在您的回答中,您会看到该名称重复了两次,例如abc 来了两次。我需要的名字不应该重复......它必须是 abc,sent,jan 21 2014,received, jan 22 2014
    • 另外,在 currentdirection 列中 - 名称即将到来,在 receiveddate 列中附加了“received”,最后收到的日期根本没有列名:(
    【解决方案2】:

    您可以使用此join 命令来完成此操作。第一个文件是1.csv,第二个文件是2.csv

    join -1 1 -2 1 -t, -a 1  1.csv 2.csv | sed "s/Direction,Date/currentDirection,receivedDate/2"
    

    输出:

    name,Direction,Date,currentDirection,receivedDate
    abc,sent,Jan 21 2014 02:06,received,Jan 22 2014 02:06
    xyz,sent,Nov 21 2014 01:09,received,Nov 22 2014 02:06
    pqr,sent,Oct 21 2014 03:06 
    

    解释:

    您想加入两个文件中的第一个字段,因此-1 1 -2 1

    您想使用逗号,因此-t,

    您想显示文件 1 中所有不匹配的记录,因此 -a 1,如果需要,您还可以附加 -a 2。

    sed 命令中的 /2 告诉 sed 替换第二次出现

    【讨论】:

    • 太好了,它的工作完美!但我需要的是,第 4 列和第 5 列的名称不同。你能根据这个需要修改你的命令吗?
    • 你能否进一步解释一下,如果我使用 -a 2 会做什么?我明白了,-a 1 用于显示文件 1 中所有不匹配的记录。那么 -a 2 会做什么?它会显示文件2的所有记录吗?那么文件 1 记录呢?
    • 这是 -a 的作用:打印来自文件 FILENUM 的不可配对行,其中 FILENUM 为 1 或 2,对应 FILE1 或 FILE2
    • 运行 join --help 以获得更多选项。
    • 感谢您的解释。您给定的命令很短,更容易理解:)
    猜你喜欢
    • 1970-01-01
    • 2019-06-28
    • 2015-12-22
    • 2015-01-18
    • 1970-01-01
    • 1970-01-01
    • 2017-09-14
    • 2016-10-19
    • 1970-01-01
    相关资源
    最近更新 更多