次のようにリンクされた電子メールを含むファイルがあります。
id emails
1 [email protected]
2 [email protected]
3 [email protected],[email protected],[email protected]
各行には異なる電子メールしかありませんが、上の1行と3行に示すように、1行から別の行に重複する可能性があります。ファイルが次のように見えるように、ファイルから重複エントリを削除する必要があります。
id emails
1 [email protected]
2 [email protected]
3 [email protected],[email protected]
これは、各行とその後のすべての行を確認する必要があることを意味します。私が持っているデータの量を考えると、どんな種類の繰り返しスクリプトでもこれは可能ではありません。私はこれを達成する簡単な(または少なくとも実行可能な)方法があると思います。アッまたはsedしかし、まだ見つかりませんでした。
答え1
以下は、正確な入力形式で動作し、迅速に実行されるsedソリューションです。
sed -rz 's:[ \t]+:,:g;s:$:,:mg;:l;s:,([^,]+),(.*),\1,:,\1,\2,:;tl;s:,$::mg;s:^([^,]+),:\1\t:mg' file.csv
仕組み:
"-z"フラグはファイル全体をロードするため、次のコードはデフォルトのようにすべての行に適用されるのではなく一度だけ適用されます。
#transform input format to actual CSV format
s:[ \t]+:,:g;s:$:,:mg;
#loop while the s command can still find and replace
:l;
#main code: find two identical cell values anywhere and delete the latter
#on a very big file this can suffer from backtracking nightmare
s:,([^,]+),(.*),\1,:,\1,\2,:;
tl;
#transform format back
s:,$::mg;s:^([^,]+),:\1\t:mg
答え2
ファイルが以下の実際のcsvファイル(simple-csv)の場合は、次のawk
コマンドを使用できます。
入力する:
[email protected]
[email protected]
[email protected],[email protected],[email protected]
注文する:
awk -F, '{ COMMA="";i=0; while (++i<=NF) {
$1=$i; printf (!seen[$1]++)?COMMA$i:""; COMMA=","}; print ""
}' infile.csv
出力:
[email protected]
[email protected]
[email protected],[email protected]
それ以外の場合、入力が質問に提供されているのと同じ場合は、次のものを使用できます。
awk 'NR==1; NR>1{id=$1"\t"; COMMA=$1="";split($0, ar, /,| /);
for(i in ar){if(ar[i]!=""){printf(!seen[ar[i]]++)?id""COMMA""ar[i]:""; COMMA=",";id=""}
} print ""}' infile
出力:
id emails
1 [email protected]
2 [email protected]
3 [email protected],[email protected]