Bash / Shell:如何从列中删除csv文件中的重复项?

时间:2014-08-22 15:25:43

标签: bash shell sorting csv uniq

我有一个用;分隔的csv。我需要删除第2列和第3列的内容不唯一的行,并将材料传递到标准输出。

示例输入:

irrelevant;data1;data2;irrelevant;irrelevant  
irrelevant;data3;data4;irrelevant;irrelevant  
irrelevant;data5;data6;irrelevant;irrelevant  
irrelevant;data7;data8;irrelevant;irrelevant  
irrelevant;data1;data2;irrelevant;irrelevant  
irrelevant;data9;data0;irrelevant;irrelevant  
irrelevant;data1;data2;irrelevant;irrelevant  
irrelevant;data3;data4;irrelevant;irrelevant  

期望的输出

irrelevant;data5;data6;irrelevant;irrelevant  
irrelevant;data7;data8;irrelevant;irrelevant  
irrelevant;data9;data0;irrelevant;irrelevant  

我找到了只有第一行打印到输出的解决方案:

sort -u -t ";" -k2,1 file  

但这还不够。

我尝试使用uniq -u,但我找不到只检查几列的方法。

3 个答案:

答案 0 :(得分:5)

使用awk

awk -F';' '!seen[$2,$3]++{data[$2,$3]=$0}
      END{for (i in seen) if (seen[i]==1) print data[i]}' file
irrelevant;data5;data6;irrelevant;irrelevant
irrelevant;data7;data8;irrelevant;irrelevant
irrelevant;data9;data0;irrelevant;irrelevant

说明:如果$2,$3数组中不存在seen组合,则$2,$3中存储密钥为data的新条目整数记录的数组。每次$2,$3条目找到时,$2,$3的计数器都会递增。然后最后打印出counter==1的条目。

答案 1 :(得分:-1)

如果订单很重要,并且您可以使用perl,那么:

perl -F";" -lane '
    $key = @F[1,2]; 
    $uniq{$key}++ or push @rec, [$key, $_] 
}{ 
    print $_->[1] for grep { $uniq{$_->[0]} == 1 } @rec' file
irrelevant;data5;data6;irrelevant;irrelevant  
irrelevant;data7;data8;irrelevant;irrelevant  
irrelevant;data9;data0;irrelevant;irrelevant  

我们使用column2和column3来创建复合键。我们通过向第一次出现的行推送键和行到数组rec来创建数组数组。

END块中,我们检查该事件是否是唯一发生的事件。如果是这样,我们继续打印线。

答案 2 :(得分:-1)

awk '!a[$0]++' file_input > file_output

这对我有用。它比较了整条线。