【问题标题】:Linux Bash commands to remove duplicates from a CSV file用于从 CSV 文件中删除重复项的 Linux Bash 命令
【发布时间】:2014-10-13 03:15:41
【问题描述】:

我将合并多个 CSV 文件。我想做的是:

1) 从文件中删除重复的行,但是,我需要检查多个列作为重复项的标准。我该怎么做?

2) 然后创建第二个输出文件以查看删除的内容会很好,以防某些不应该删除的内容被删除。

3) 创建一个项目列表作为输入文件运行(如果该行在该特定列中包含该单词,则删除整行。

如果有人可以帮助我执行此操作的命令,那就太好了!如果我需要澄清,请告诉我。

这是数据的样例(这里是建议的示例):

我有一个这样的 csv 文件:

column1    column2

john       kerry
adam       stephenson
ashley     hudson
john       kerry
etc..

我想从此文件中删除重复项,只为 1 处的问题获取:

column1    column2

john       kerry
adam       stephenson
ashley     hudson

对于问题 3,我想采用第二个列表...意思是第一个列表的输出并进一步擦洗。我想要一个像 input.txt 这样的文件,其中包含:

adam

那么,最终的输出将是:

column1    column2

john       kerry
ashley     hudson

因此,示例中的 input.txt 文件包含单词 adam(这样我可以制作一长串单词以在 input.txt 文件中检查)。对于#3,我需要一个代码片段,它将检查 CSV 的所有行的第 1 列中的所有单词输入文件,然后从 csv 中删除任何匹配项。

【问题讨论】:

  • Perl 和 awk 非常适合这种工作。如果您提供示例输入文件并展示您已经尝试过的内容,您可能会得到更好的答案。
  • 刚刚添加。我对 Perl 或 Awk 一无所知,但我知道 Bash。我希望有人能给我 Bash 命令。
  • 只是为了确保:您检查 some 列是否相等,这意味着 some 列可能不同但仍被视为相等(换句话说:uniq 不起作用)?
  • 我同意 tkocmathla... 您可能希望使用比 bash 更适合此类工作的东西来执行此操作。我想将 python 添加到列表中。
  • 我会将您的 csv 文件放入 sqlite 数据库或其他东西中。如果您尝试基于某些列组合来比较相等性,您会发现在 bash 中这非常困难。

标签: linux bash csv


【解决方案1】:

您需要为问题 3 提供更多详细信息,但对于问题 1 和 2,以下awk 单行将起作用。

awk 'seen[$0]++{print $0 > "dups.csv"; next}{print $0 > "new.csv"}' mycsv

为了清楚起见,添加了一些空格:

awk 'seen[$0]++ {
  print $0 > "dups.csv"; next
}
{
  print $0 > "new.csv"
}' mycsv

这不会向 STDOUT 打印任何内容,但会创建两个文件。 dups.csv 将包含所有已删除的重复项(即,如果同一行有 5 个条目,则此文件将包含 4 个作为重复项删除的条目),new.csv 将包含所有唯一行。

seen[$0]++ 是我们对每一行进行的测试。如果该行存在于我们的数组中,它将被插入到dups.csv 文件中,我们将使用next 移动到下一行。如果行不存在,我们将该行添加到数组中并将其写入new.csv 文件。

使用$0 表示整行。如果你想指定更少的列,你可以这样做。您只需要根据分隔符设置输入字段分隔符。您提到了csv,但我没有看到任何comma 分隔符,所以我使用默认分隔符[[:space:]]+

另外,它是用逗号分隔的,我只是把示例数据放在上面。那么,如果我想使用上面的示例,但只想测试第 3 列和第 4 列(使用 seen 命令),我将如何在逗号分隔的文件中执行此操作?

对于真正的csv,只需将字段分隔符设置为,seen 不是命令。它是一个将列保留为键的哈希。所以你将上面的命令修改为:

awk -F, 'seen[$3,$4]++{print $0 > "dups.csv"; next}{print $0 > "new.csv"}' mycsv

更新:

一旦您使用上述命令获得一个没有重复的列表。我们只剩下:

$ cat new.csv 
john,kerry
adam,stephenson
ashley,hudson

$ cat remove.txt 
adam

$ awk -F, 'NR==FNR{remove[$1]++;next}!($1 in remove)' remove.txt new.csv 
john,kerry
ashley,hudson

【讨论】:

  • 默认分隔符是[[:space:]]+,不是吗?
  • @TomFenech 是的,打算编写[:space:] 的序列,但[[:space:]]+ 更短。会更新的,谢谢!
  • 谢谢!我刚刚更新了问题 3。此外,它是用逗号分隔的,我只是将示例数据放在上面。那么,如果我想使用上面的示例,但只想测试第 3 列和第 4 列(使用 seen 命令),我将如何在逗号分隔的文件中执行此操作?
  • @Peaceful_Warrior 不确定我是否关注。创建仅包含adam 的文件的算法是什么?将更新帖子以回答您的其他问题。
  • @Peaceful_Warrior 谢谢,但你还没有提到为什么列表只包含adam 而不是johnashley
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-24
  • 2014-10-16
  • 2020-08-04
  • 2020-05-18
  • 2016-03-29
  • 2023-03-27
  • 1970-01-01
相关资源
最近更新 更多