我有以下文件:
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) 当前行与保持行中的任何位置都不匹配。
- [操作] 将当前行移动到末尾。
- a) 当前行与保留行中的某处匹配且 false:false。
结果
AA,false
BB,false
CC,false
DD,true
答案4
两遍解决sort
方案
sort -k1,1 -k2,2 -t, file | sort -k1,1 -t, -u
第一遍按sort
字段对记录进行聚类,每个记录块前面的记录共享公共字段值。第二遍设置为为字段内的每个不同值生成一条记录。由于意味着稳定排序,因此生成的一条记录是字段内每个不同值遇到的第一个记录- 由于第一遍完成的工作,这是第二个字段中的记录1
false
true
1
sort
1
-u
-u
1
false
sort