我有以下.csv文件(大小很大〜几百MB到GB,几列~20,没有排序,由&#34分隔;"):
name1,address1,town1,zip1,....,category1
name2,address2,town2,zip2,....,category2
name3,address3,town3,zip3,....,category3_1
name3,address3,town3,zip3,....,category3_2
name3,address3,town3,zip3,....,category3_3
name4,address4,town4,zip4,....,category4_1
name4,address4,town4,zip4,....,category4_2
name4,address4,town4,zip4,....,category4_3
name4,address4,town4,zip4,....,category4_4
name5,address5,town5,zip5,....,category5
我需要将行连接到只有一行,如果它们具有相同的行并且仅在类别上有所不同,并使用&#34 ;;"将这些类别放到最后一列中。分隔符,例如:
name1,address1,town1,zip1,....,category1
name2,address2,town2,zip2,....,category2
name3,address3,town3,zip3,....,category3_1;category3_2;category3_3
name4,address4,town4,zip4,....,category4_1;category4_2;category4_3;category4_4
name5,address5,town5,zip5,....,category5
我尝试用阅读...;做读...完成< $ file ,但这只是按2行读取每个文件并且不会比较每一行。还试图将类别信息保存到数组并创建合并类别列,但在某些行脚本只是停止按我想要的方式解析它。 在 awk 或 sed 中完成此操作会很棒,因为在阅读包含大量列的大文件时,读取非常慢,但是如果用其他语言做到这一点的更好的方法我会好好的。 非常感谢!
答案 0 :(得分:0)
两个答案:
Shell + sed
您可以对此(特定)案例使用sed:
(嗯,太快了!我错了!
$ sed -e ':;N;s/^\(\([^,]\+,\)\{5\}\)\(.*\)*\n\1/\1\3;/;t' file.csv
)
$ sed -e ':a;$!N;s/^\(\([^,]\+,\)\{5\}\)\(.*\)*\n\1/\1\3;/;ta;P;D;$!ba' file.csv
用于检索列数(-1)又称分隔符数:
read line <file.csv
cols="${line//,}"
cols=$[${#line}-${#cols}]
sed -e "
:a;
$!N;
s/^\(\([^,]\+,\)\{$cols\}\)\(.*\)*\n\1/\1\3;/;
ta;
P;
D;
$!ba
" file.csv
name1,address1,town1,zip1,....,category1
name2,address2,town2,zip2,....,category2
name3,address3,town3,zip3,....,category3_1;category3_2;category3_3
name4,address4,town4,zip4,....,category4_1;category4_2;category4_3;category4_4
name5,address5,town5,zip5,....,category5
仅限最后一个字段!
有一种基于最后一个逗号的简单方法:
sed -e ":;$!N;s/^\(.*,\)\([^,]*\)*\n\1/\1\2;/;t;P;D;$!b" file.csv
(用于在行尾添加不需要的 CR :
sed -e ':;$!N;s/\o015//g;s/^\(.*,\)\([^,]*\)*\n\1/\1\2;/;t;P;D;$!b'
)
纯粹的bash(没有叉子)
这可以使用纯bash来完成(使用dash和busybox也可以正常工作!),但也许更适合小文件:
while read line;do
if [ "${line%,*}" = "${last%,*}" ];then
last="$last;${line##*,}"
else
echo "$last"
last="$line"
fi
done < file.csv
echo "$last"
name1,address1,town1,zip1,....,category1
name2,address2,town2,zip2,....,category2
name3,address3,town3,zip3,....,category3_1;category3_2;category3_3
name4,address4,town4,zip4,....,category4_1;category4_2;category4_3;category4_4
name5,address5,town5,zip5,....,category5
注意:无需知道列数,因为这是基于最后一个逗号。