根据字段的唯一子集进行计数

根据字段的唯一子集进行计数

我有一个文本文件,其结构如下:

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命令,我可以委托-uuniq -u,这样我就可以使用 选项-funiq此选项忽略给定数量的前导字段。你想忽略第一个字段,所以-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

相关内容