【问题标题】:Get difference between two csv files based on column using bash使用 bash 根据列获取两个 csv 文件之间的差异
【发布时间】:2019-08-07 07:09:40
【问题描述】:

我有两个 csv 文件 a.csvb.csv,它们都没有标题,并且一行中的每个值都由 \t 分隔。

1   apple
2   banana
3   orange
4   pear
apple   0.89
banana  0.57
cherry  0.34

我想减去这两个文件,并得到a.csv 中的第二列和b.csv 中的第一列之间的差异,就像a.csv[1] - b.csv[0] 这样会给我另一个文件c.csv 看起来像

orange
pear

我不想使用 python 和其他编程语言,而是想使用 bash 命令 来完成此任务,发现awk 会有所帮助,但不太确定如何编写正确的命令。 Here 是另一个类似的问题,但第二个答案使用 awk '{print $2,$6-$13}' 来获取值之间的差异而不是出现次数。

感谢并感谢您的任何帮助。

【问题讨论】:

  • 您确定您的预期输出已完全显示吗?我猜你错过了cherry
  • @Zelnes:OP 希望第一个文件中的条目(第二列)在第二个文件(第一列)中不存在

标签: csv awk


【解决方案1】:

您可以通过您引用的链接中的Steve's answer 轻松完成此操作,只需稍作调整即可。不确定paste 的其他答案能否帮助您解决此问题。

从第二个文件b.csv 创建一个哈希映射,并再次将其与a.csv 中的第二列进行比较

awk -v FS="\t" 'BEGIN { OFS = FS } FNR == NR { unique[$1]; next } !($2 in unique) { print $2 }' b.csv a.csv

要将输出重定向到新文件,请在上一条命令的末尾附加 > c.csv

在读取制表符分隔文件时,将字段分隔符(输入和输出)设置为\t

  1. FNR == NR { action; } { action } f1 f2 是一种通用结构,您可以在许多awk 命令中找到它,如果您必须对多个文件执行操作,它就可以工作。 FNR == NR 之后的块在提供的第一个文件参数上执行,{..} 中的下一个块在第二个文件参数上运行。
  2. unique[$1]; next 部分在文件b.csv 的第一列中创建一个以键作为值的哈希映射unique{..} 中的部分适用于文件中的所有列。
  3. 在这个文件被完全处理后,在下一个文件a.csv,我们做!($2 in unique),这意味着,标记那些在第二个文件中$2不是unique哈希键的一部分的行-从第一个文件生成的地图。
  4. 在这些行上仅打印第二列名称{ print $2 }

【讨论】:

  • 感谢您的详细解释,这正是我所需要的!
【解决方案2】:

如果你想使用 Miller (https://github.com/johnkerl/miller),一个干净简单的工具,命令可以是

mlr --nidx --fs "\t" join --ul --np -j join -l 2 -r 1  -f 01.txt then cut -f 2 02.txt

它给你

orange
pear

这是一个join,它不会发出配对的记录,而是从左侧文件发出未配对的记录。

【讨论】:

  • 这也很有帮助,我会研究其他任务。
【解决方案3】:

假设您的真实数据按您关心的列排序,就像您的示例数据一样:

$ comm -23 <(cut -f2 a.tsv) <(cut -f1 b.tsv)
orange
pear

这使用comm 打印出第一个文件中不在第二个文件中的条目,然后使用cut 获取您关心的列。

如果尚未排序:

comm -23 <(cut -f2 a.tsv | sort) <(cut -f1 b.tsv | sort)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-02-14
    • 2017-05-25
    • 1970-01-01
    • 2019-03-26
    • 1970-01-01
    • 2011-03-28
    相关资源
    最近更新 更多