2017-03-03 114 views
0

example1.csvCSV删除与重复的值的所有行中的一列

id1, value1 
id2, value2 
id3, value3 
id1, value4 

example2.csv

"06e04,0428","405872,8637110" 
"06e04,0428","405872,8637111" 
"06e04,0429","405872,8637110" 
"06e04,0430","405872,8637110" 
"06e04,0431","405872,8637111" 

需要删除与在列1重复的值的行,以输出如下

需要输出

example1_out。 CSV

id2, value2 
id3, value3 

example2_out.csv

"06e04,0429","405872,8637110" 
"06e04,0430","405872,8637110" 
"06e04,0431","405872,8637111" 

有解决方案,以除去保留的重复记录一个在本SO question重复记录。但是在这种情况下,需要从输出中排除列1具有重复值的所有行。

+0

你已经标记了你的问题'shell'。你是不是指'bash'? – ghoti

+0

@Grzesiek - 你能否添加nodejs答案? – user3206440

+0

@ user3206440我很抱歉使用awk的选定解决方案更短。 – Grzesiek

回答

1

awk可以做,在一个命令:

awk -F, '{arr[$1]=$0} seen[$1]++{delete arr[$1]} END{for (i in arr) print arr[i]}' file.csv 

id2, value2 
id3, value3 

为您编辑的问题使用:

awk -F'","' '{arr[$1]=$0} seen[$1]++{delete arr[$1]} END{for (i in arr) print arr[i]}' file.csv 

"06e04,0429","405872,8637110" 
"06e04,0430","405872,8637110" 
"06e04,0431","405872,8637111" 
+2

请注意,这不会保留行顺序'id3,value3 id2,value2' –

+0

当列1的值为','时,这不起作用 - 请参阅更新的问题。 – user3206440

+0

我已根据您编辑的问题修改了我的答案。检查给出预期输出的更新答案。 – anubhava

1
cut -f1 -d, somecsv.csv | sort | uniq -u | grep -Ff- somecsv.csv 

第一条命令从输入中提取第一列。第二个命令对ID进行排序,因此下一个命令只能列出唯一的ID。最后的grep将采用唯一的ID并在输入文件中搜索它们。

+0

嗯......这也会匹配col1中的文本包含在其他colums中的行......例如,'id1,valid2' – jm666

+1

因此,将'grep -Ff -'改为'sed's/^/^ /'| grep -f-'。同样,如果第一列包含特殊字符,它可能会中断... – choroba

0

您可以使用awk

awk -F "," '{ 
    if (length(arr[$1]) == 0){ 
     arr[$1]=$0 
     order[i++]=$1 
    } 
    else{ 
     delete arr[$1] 
    } 
} 
END { 
    for (i = 1; i < length(order); i++) { 
     print arr[order[i]] 
    } 
}' somecsv.csv 

它存储阵列中的所有项目,如果它发现两次删除该项目。顺序将予以保留一个额外order阵列

1

这里有一个较短的awk选项。

awk -F, 'NR==FNR{a[$1]++;next} a[$1]<2' file.csv file.csv 

这读取文件两次 - 一次来填充第一场的计数器阵列,并且第二次打印其计数小于2

如果您更愿意线为此在纯壳,而不是awk和你的shell是bash,你可以像这样的东西得到了类似的功能:

$ declare -A a=() 
$ while IFS=, read f _; do ((a[$f]++)); done < file.csv 
$ declare -p a 
declare -A a=([id1]="2" [id3]="1" [id2]="1") 
$ while IFS=, read f1 f2; do [ "${a[$f1]}" -lt 2 ] && printf '%s,%s\n' "$f1" "$f2"; done < file.csv 
id2, value2 
id3, value3 

再次,这是两个步骤 - 填充计数器阵列第一,第二步通过文件和打印approp划线。

相关问题