我有一个文本文件,其结构如下:
P,ABC,DEF
P,GHI,JKL
B,ABC,DEF
B,MNO,PQR
我想要计算字段 2 和 3 相同的行出现的次数,同时保留字段 1。因此,输出将如下所示:
2,P,ABC,DEF
1,P,GHI,JKL
2,B,ABC,DEF
1,B,MNO,PQR
uniq -c
不会起作用(据我所知)因为它不能按字段分隔。sort -u -t, -k2,2 -k3,3
也不会起作用,因为它不能计数(据我所知)并且写入的命令只会将第三行作为重复项销毁,同时保留第一行。
最终,我需要返回的是第 2 行和第 4 行,因为字段 2 和字段 3 的组合是唯一的。但是,我需要保留字段 1,因为它指的是字段 2 和字段 3 源自哪个数据集(在现实世界中)。因此,我真正需要的是返回第 2 行和第 4 行的解决方案。
因此,以下解决方案同样有效:
P,GHI,JKL
B,MNO,PQR
答案1
根据你的sort
命令,我可以委托-u
给uniq -u
,这样我就可以使用 选项-f
。uniq
此选项忽略给定数量的前导字段。你想忽略第一个字段,所以-f1
。为了使它工作,我需要将每个字段转换,
为空白并转回:
<data sort -t, -k2,2 -k3,3 | tr , ' ' | uniq -u -f1 | tr ' ' ,
虽然这适用于您的示例数据集,但当有空白时它会失败。这是因为uniq -f
将字段识别为[[:blank:]]*[^[:blank:]]*
。如果您的实际数据中有空白,那么它们将uniq
识别比您想要的更多的字段。
为了解决这个问题,您需要将实际的空格转换为非空格,执行uniq
,然后再转换回来。在 POSIX 语言环境中[:blank:]
仅包含空格和制表符;在其他语言环境中可能包含更多。
以下命令暂时将空格转换为 DC1 字符(设备控制 1,八进制021
),并将制表符转换为 DC2(设备控制 2,八进制022
):
<data sort -t, -k2,2 -k3,3 | tr ' \t,' '\021\022 ' | uniq -u -f1 | tr '\021\022 ' ' \t,'
如果数据不包含 DC1 或 DC2,它就应该可以工作。
甚至如果你tr
不支持多字节字符,转换不会干扰UTF-8的多字节字符,因为UTF-8中多字节字符中每个字节的最高有效位始终为1
,而对于DC1或DC2则为0
。