【问题标题】:Bash/awk: Find duplicates based on two columns, keep rows based on values in other columnsBash/awk:根据两列查找重复项,根据其他列中的值保留行
【发布时间】:2020-10-01 03:52:16
【问题描述】:

我之前的问题 (here) 有点复杂。

  1. 我需要根据代表 4:标识符、5:日期的第 4 列和第 5 列的组合来识别逗号分隔的文本文件中的重复条目。这两列可以简单地连接起来。

  2. 如果有重复,我需要根据另一列的子字符串进行检查,它表示一个 int 值。应保留具有较高值的​​副本。 创建子串示例:cut -d"," -f14 file.txt | grep -o "N0[0-9]{3}" | sed 's/N0//g'

  3. 如果 int 值相同,我需要根据代表日期的第 9 列执行另一次检查。应保留日期较晚的行。

示例数据:

xyz,xyz,xyz,X08ABC,20200804,xyz,xyz,xyz,2020-08-17T20:08:27.000000Z,xyz,xyz,xyz,xyz,long_string_N0809_bla
xyz,xyz,xyz,X08ABC,20200804,xyz,xyz,xyz,2020-09-25T16:18:43.000000Z,xyz,xyz,xyz,xyz,long_string_N0809_bla

在示例中,将保留第三列,而丢弃前两列。它们都是重复的(col4+col5 = 相同),第 14 列的 int 值在第 2 行和第 3 行最高,第 9 列中的日期在第 3 行比第 2 行晚。

如果我可以保持原始文件中的行顺序,那是一个加分项 - 但不是必须的。

编辑:如果这可以在 awk 中以某种可读的方式完成,那么拥有一个 awk 解决方案会很棒。我认为这是可能的,但我对 awk 中的多个操作感到非常困惑。

【问题讨论】:

    标签: csv awk


    【解决方案1】:

    我花了很长时间阅读其他问题、手册等,但我认为这应该是一个可能的解决方案。它确实需要排序,所以不幸的是行的顺序并没有保持不变。此外,它依赖于始终具有相同长度的列条目,这有很多潜在的麻烦。

    sort -t, -k 14.15,14.17r -k9.1,9.4r -k9.6,9.7r -k9.9,9.10r file.txt | awk -F, '{OFS=","} {print $0, $4"_"$5}' | awk -F, '!a[$15]++'

    这将根据第 14 列 (809) 中的 int 值子集和第 9 列中的日期对行进行排序(按年、月、日期排序)。然后,创建一个组合 col 4 和 col5 的新列,以识别重复项。最后一个 awk 命令只保留那些最先出现的重复行 - 这也是为什么需要首先对所有内容进行排序的原因。

    欢迎改进!

    【讨论】:

    • 1) 数字反转一列并反转日期就足够了,这些是您的二次排序。 2) 对于重复项,您可以使用字段组合作为哈希键,无需将它们连接为附加字段。 sort -t, -rnk14 -rk9 | awk -F, '!seen[$4,$5]++'
    • 谢谢!两个问题:我不是 100% 确定点 1)。我仍然需要将日期(第 9 列)拆分为年、月、日,因为它由- 分隔。还是我错过了什么?简单地按数字对第 14 列进行排序也不起作用,除非我对包含感兴趣的数值的位置进行子集化。
    • man sort 了解每个字段可以使用的排序类型。对于 9,它只是按字母顺序排序,是否颠倒,根据您的需要。对于 14,我只看到两个示例行,但它似乎混合了数字和字母,尝试 -V、-h 和/或搜索这个,它有据可查。
    猜你喜欢
    • 2016-02-27
    • 1970-01-01
    • 1970-01-01
    • 2017-06-02
    • 2020-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多