根据另一列的值删除重复项


9

我有以下文件:

AA,true
AA,false
BB,false
CC,false
BB,true
DD,true

我正在尝试查找重复项,并删除列值等于的行true

输出应为:

AA,false
BB,false
CC,false
DD,true

2
所以..仅true当它是第一列的第一个实例时才保留吗?
DopeGhoti

1
@RomanPerekhrest可能是因为它是uniq条目,并按“原样”显示
George Vasiliou

@RomanPerekhrest因为DD,true不是重复的,所以我们没有另一行与DD,false。
Hani Gotc '17

AA,true AA,false AA,false AA,false在这种情况下应该是什么输出?我了解,仅当该行具有重复且同时包含true时,才应删除该行。false在任何情况下,所有行均应保持不变。也就是说,在这种情况下,仅AA, true将被删除。但是所有答案只剩下一行- AA,false。只是有趣
而已

Answers:


9
awk -F, '$2 == "false" {data[$1]=$2 } $2=="true" { if ( data[$1]!="false" ) { data[$1]=$2 } } END { OFS=","; for (item in data) { print item,data[item] }}' input

垂直展开脚本进行解释:

BEGIN {
   FS=","         # Set the input separator; this is what -F, does.
}
$2 == "false" {    # For any line whose second field is "false", we
   data[$1]=$2     # will use that value no matter what.
}
$2=="true" {                    # For lines whose second field is "true",
   if ( data[$1]!="false" ) {   # only keep if if we haven't yet seen a
      data[$1]=$2               # "false"
   }
}
END {                           # Now that we have tabulated our data, we
   OFS=","                      # can print it out by iterating through 
   for (item in data) {         # the array we created.
      print item,data[item]
   }
}

@DopeGhoti很好地解释了!您为此获得了+1。
Valentin Bajrami

14

简单版本:

sort input.txt | awk -F, '!a[$1]++'

“ false”在“ true”之前按字母顺序排序,并且此处的Awk命令仅针对每个不同的第一字段值保留第一行。

如果要保留“ true”而不是“ false”,请对其进行反向排序,将其传递给相同的Awk命令,然后再次对其进行反向排序。


1
同样,如果有-u选项,sort input.txt | sort -t, -u -k1,1
Sundeep

2
@Sundeep为什么要使用两个sort电话?为什么不只是sort -ut, -k1,1 input.txt 呢?
terdon

2
@terdon,因为-u它将保留重复项中从输入文件中找到的第一行...对于给定的情况,必须先对输入进行排序,然后-u才能应用...对于ex:AA,true将被打印,而不是AA,false因为它在给定的示例中首先出现。为何awk -F, '!a[$1]++'不能单独解决此问题的相同原因
Sundeep

5
perl -F, -lane '
   exists $h{$F[0]} or $h[$h{$F[0]}=@h]=$_;
   $h=$_; /,false$/ or $_=$h for $h[$h{$F[0]}];
   END{ print for @h; }
' duplicates.file

数据结构:

  • 散列,%h其键是第一个字段(AAA,BBB,CCC等),对应的值是数字,表示遇到密钥的顺序。因此,例如,密钥AAA => 0,密钥BBB => 1,密钥CCC => 2。
  • @h其元素是按打印顺序包含的行的数组。因此,如果在数据中同时找到true和false,则false值将进入数组。OTW,如果存在一种类型的数据,则将存在。

另一种方法是使用GNU sed:

sed -Ee '
   G
   /^([^,]*),(false|true)\n(.*\n)?\1,\2(\n|$)/ba
   /^([^,]*)(,true)\n(.*\n)?\1,false(\n|$)/ba
   /^([^,]*)(,false)\n((.*\n)?)\1,true(\n|$)/{
      s//\3\1\2\5/;h;ba
   }
   s/([^\n]*)\n(.*)$/\2\n\1/;s/^\n*//
   h;:a;$!d;g
' duplicates.file

FWIW,上面列出了上述GNU sed代码的POSIX等效代码:

sed -e '
   G

   /^\([^,]*\),\(false\)\n\(.*\n\)\{0,1\}\1,\2$/ba
   /^\([^,]*\),\(false\)\n\(.*\n\)\{0,1\}\1,\2\n/ba

   /^\([^,]*\),\(true\)\n\(.*\n\)\{0,1\}\1,\2$/ba
   /^\([^,]*\),\(true\)\n\(.*\n\)\{0,1\}\1,\2\n/ba

   /^\([^,]*\),true\n\(.*\n\)\{0,1\}\1,false$/ba
   /^\([^,]*\),true\n\(.*\n\)\{0,1\}\1,false\n/ba

   /^\([^,]*\)\(,false\)\n\(\(.*\n\)\{0,1\}\)\1,true$/{
      s//\3\1\2/
      h
      ba
   }
   /^\([^,]*\)\(,false\)\n\(\(.*\n\)\{0,1\}\)\1,true\n/{
      s//\3\1\2\n/
      h
      ba
   }

   y/\n_/_\n/
   s/\([^_]*\)_\(.*\)$/\2_\1/;s/^_*//
   y/\n_/_\n/

   h;:a;$!d;g
' duplicates.file

说明

  • 在这种方法中,我们将要存储的结果最终存储在保留空间中。
  • 对于每行读取的数据,我们将保留空间附加到模式空间,以相对于保留空间的现有状态检查当前行。
  • 现在,在此比较期间可能会发生5件事:
    • a)当前行与保持行中的某处匹配,并且false:false。
      • [ACTION]由于找到了相同的错误状态,因此什么也不做。
    • b)当前行与保持行中的某处匹配,并且true:true。
      • [ACTION]由于找到了相同的真实状态,因此什么也不做。
    • c)当前行与保留行中的某处匹配,并且true:false。
      • [ACTION]由于已经存在错误状态,因此请勿执行任何操作。
    • d)当前行与保持行中的某处匹配,并且false:true。
      • [ACTION]这涉及到一些工作,因为我们需要在与true完全相同的位置替换false线。
    • e)当前行与保持行中的任何地方都不匹配。
      • [ACTION]将当前行移到末尾。

结果

AA,false
BB,false
CC,false
DD,true

3

对于每条输入行,当尚未存储该a键的值时,才将第二个字段的值存储在关联数组中(使用第一个字段作为数组的键)。使用的输入和输出字段分隔符。阅读完所有输入行后,打印出数组。false,

$ awk -F, -v OFS=, 'a[$1] != "false" { a[$1] = $2 };
                    END { for (i in a) {print i,a[i]} }' truefalse.txt
AA,false
BB,false
CC,false
DD,true

此版本与DopeGhoti版本之间的显着区别是,此版本完全不关心的值$2,仅关心的值(如果有)a[$1]


1

两遍sort解决方案

sort -k1,1 -k2,2 -t, file | sort -k1,1 -t, -u

第一次sort通过按字段1false记录true进行聚类,对于共享公共字段1值的每个记录块,记录在前。第二sort遍设置为在现场1礼貌下为每个不同的值产生一个记录-u。由于-u暗示稳定排序,因此产生的一个记录是字段中每个不同值遇到的第一个记录1- false由于sort第一遍的工作,该记录在第二个字段中

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.