Text-Processing
查找和替換重複項
我有一個包含串聯電子郵件的文件,如下所示:
id emails 1 jeff@email.com 2 larry@email.com 3 jprice@email.com,jeff@email.com,jeff@stacko.com
每行只有不同的電子郵件,但從一行到另一行可能存在重複,如上面第 1 行和第 3 行所示。我需要從文件中刪除重複項,以便文件如下所示:
id emails 1 jeff@email.com 2 larry@email.com 3 jprice@email.com,jeff@stacko.com
這意味著我需要檢查每一行與它後面的所有行。鑑於我擁有的數據量,這對於任何類型的迭代腳本都是不可行的。我覺得有一種簡單(或至少可行)的方法可以使用awk或sed完成此任務,但我還沒有找到任何方法。
如果您的文件是如下所示的真實 csv 文件(simple-csv),則可以使用以下
awk
命令:輸入:
jeff@email.com larry@email.com jprice@email.com,jeff@email.com,jeff@stacko.com
命令:
awk -F, '{ COMMA="";i=0; while (++i<=NF) { $1=$i; printf (!seen[$1]++)?COMMA$i:""; COMMA=","}; print "" }' infile.csv
輸出:
jeff@email.com larry@email.com jprice@email.com,jeff@stacko.com
如果沒有,並且輸入就像在您的問題中給出的一樣,您可以使用以下代替:
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 jeff@email.com 2 larry@email.com 3 jprice@email.com,jeff@stacko.com
這是一個 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