我有一个如下所示的文件
1,1230,add
1,1235,remove
2,1240,add
2,1245,remove
3,1250,add
4,1255,remove
我想打印第一个字段具有唯一值的那些行,和其中第三个字段等于add
.该示例的预期输出为
3,1250,add
或仅第一列,即
3
下面的命令给了我不同的记录,但后来我想检查第三列是否是“添加”,然后只打印输出。
awk -F ',' 'print $1' filename | uniq -u
答案1
在这种情况下,我想到了双遍方法:
awk -F',' 'NR==FNR{seen[$1]++;next} $3=="add" && seen[$1]==1' file.txt file.txt
这将处理输入文件两次(因此它作为参数被声明两次)。
- 在第一遍中,
NR
全局行计数器 等于FNR
每个文件行计数器,我们只计算遇到第一个字段的这个特定值的频率,否则立即跳过处理(语句next
)。 - 在第二遍中,我们检查第三个字段是否等于
add
,并且第一个字段仅出现一次。如果是这样,我们打印该行(因为这两个条件将计算为true
)。
答案2
由于 AdminBee 已经展示了该awk
方法,因此这是使用标准实用程序的另一种方法:
sort -t',' -k1,1 file | uniq -u -w 1 | grep 'add$'
sort
使用逗号作为分隔符并仅按字段 1 排序uniq
只打印唯一的行但检查不超过 1 (!) 每行字符- 现在
grep
以“add”结尾的行
限制:uniq
当然只检查一个字符。对于字段 1 中的两位或多位数字条目,必须对字段 1 进行预处理,例如在左侧填充零,然后相应地增加用于检查的字符数。如果您的文件已按照示例中给出的方式进行排序,则可能会跳过排序。
答案3
使用 awk 一次性完成:
awk -F ',' '
{ if ( ! seen[$1]++ )
{ if ( $3 == "add" )
keep[$1] = $0
}
else
{
if ( keep[$1] )
delete keep[$1]
}
}
END {
for (i in keep)
print keep[i]
}' infile