解释

解释

我有以下文件:

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

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

作为输出它应该是:

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

答案1

简单版本:

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

“false”按字母顺序排序在“true”之前,这里的 Awk 命令仅保留每个不同的第一个字段值的第一行。

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

答案2

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]
   }
}

答案3

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

数据结构:

  • 其键是第一个字段(AAA、BBB、CCC 等)的哈希%h,对应的值是告诉键遇到顺序的数字。因此,例如,密钥 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。
      • [操作] 由于发现相同的错误状态,则不执行任何操作。
    • b) 当前行与保持行中的某处匹配且 true:true。
      • [行动] 既然找到了相同的真实状态,那么什么也不做。
    • c) 当前行与保持行中的某处匹配且 true:false。
      • [操作] 由于错误状态已存在,因此不执行任何操作。
    • d) 当前行与保留行中的某处匹配且 false:true。
      • [操作] 这涉及到一些工作,因为我们需要在与真线完全相同的位置替换假线。
    • e) 当前行与保持行中的任何位置都不匹配。
      • [操作] 将当前行移动到末尾。

结果

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

答案4

两遍解决sort方案

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

第一遍按sort字段对记录进行聚类,每个记录块前面的记录共享公共字段值。第二遍设置为为字段内的每个不同值生成一条记录。由于意味着稳定排序,因此生成的一条记录是字段内每个不同值遇到的第一个记录- 由于第一遍完成的工作,这是第二个字段中的记录1falsetrue1sort1-u-u1falsesort

相关内容