【问题标题】:bash remove duplicates from four columns where order does not matter [duplicate]bash从顺序无关紧要的四列中删除重复项[重复]
【发布时间】:2020-01-20 07:51:22
【问题描述】:

我有一个文件,我想检查 4 列的内容,这些列之间的顺序可以颠倒,这意味着如果列是 a、b、c、d,那么它们也可以显示为c、d、a、b。因此,a、b 和 c、d 列被锁定,但可以相互交换。

我在这里找到了类似的帖子 remove redundancy in a file based on two fields, using awk 但是解决方案根本不起作用

即使只有两列

a;b
d;a
b;a
r;f
r;y
a;b
a;d

如果我应用提供并正确给出的解决方案,我最终会得到重复

$ awk '!seen[$1,$2]++ && !seen[$2,$1]++' file
a;b
d;a
b;a
r;f
r;y
a;d

如你所见,还有 a;b 和 b;a

任何使这项工作的建议,考虑到也会有四列,例如

Dallas;Texas;Berlin;Germany
Paris;France;Tokyo;Japan
Berlin;Germany;Dallas;Texas
Florence;Italy;Dublin;Ireland
Berlin;Germany;Texas;Dallas

应该给

Dallas;Texas;Berlin;Germany
Paris;France;Tokyo;Japan
Florence;Italy;Dublin;Ireland
Berlin;Germany;Texas;Dallas

注意最后一行不应该被删除,因为那是不同的记录,所以 a,b 和 c,d 应该被认为是锁定的一对,所以 a,b,c,d 或 c,d,a,b 应该被视为重复但不是其他情况。

【问题讨论】:

  • 前导空格是文件的一部分吗?如果不存在则从描述中删除
  • 我将其标记为重复,因为 OP 知道如何解决问题,但忘记定义字段分隔符。副本使用:,而这里使用;。然而,这并没有太大的区别。同时,该帖子也应标记为与OP中提到的帖子的重复。
  • @kvantour:同意你的第一部分。对于具有多个字段的行的部分,仅设置 ; 将不起作用。按照前面的逻辑,虽然有 2^4 个字段的变体看起来不太好。如果不得不按多个单词对行进行分组,那么这将适用于此
  • @Inian OP 在开头声明 如果列是 a,b,c,d 那么它们也可以显示为 c,d,a,b。 所以本质上问题是相同的。 awk -F ';' '!seen[$1,$2,$3,$4]++ && !seen[$3,$4,$2,$1]++' file。在这种情况下,没有 2^4 变体。
  • 抱歉,前导空格不是文件的一部分,我编辑了它。

标签: awk


【解决方案1】:

对于具有两个字段的原始示例,您错过了将; 定义为输入字段分隔符。如果你运行它,同样会起作用

awk -F';' '!seen[$1,$2]++ && !seen[$2,$1]++' file

对于分隔符上的一行中的多个记录,最好按字母顺序对这些记录进行排序并使用逻辑。无论元素在一行中的顺序如何,以下逻辑都有效。

由于asort() 功能需要GNU awk

以下情况不需要输入和输出分隔符,因为在每一行上,我们使用由; 分割的记录来构造唯一键并在唯一时打印整行。

awk '{
       split($0, arr, ";"); key=""; 
       asort(arr);
       for (i=1; i<=length(arr); i++) { 
         key = ( key FS arr[i] )  
       }
    }!unique[key]++' file

以所谓的单线(又名不可读)方式

awk '{ split($0, arr, ";"); asort(arr); key=""; for (i=1; i<=length(arr); i++) { key = ( key FS arr[i])  }; }!unique[key]++' file

如 cmets 中所述,如果 a,b,c,d 的可能替代品只是 c,d,a,b,那么执行以下操作就足够了

awk -F';' '!seen[$1,$2,$3,$4]++ && !seen[$3,$4,$1,$2]++' file 

【讨论】:

  • 对不起,它不认为 a,b 和 c,d 是一对。例如拿达拉斯;德克萨斯;柏林;德国巴黎;法国;东京​​;日本柏林;德国;达拉斯;德克萨斯佛罗伦萨;意大利;都柏林;爱尔兰柏林;德国;德克萨斯;达拉斯 使用您的脚本,最后一行也将被删除,但将是一个单独的记录。
  • 看来awk -F';' '!seen[$1,$2,$3,$4]++ && !seen[$3,$4,$1,$2]++' 文件完成这项工作
猜你喜欢
  • 1970-01-01
  • 2016-12-28
  • 2020-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-17
  • 2019-02-13
  • 2011-10-07
相关资源
最近更新 更多