我有以下.csv文件(大小巨大,数百MB到GB,几列~20,未排序,用","分隔):
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
如果行相同,但仅在类别上不同,则我需要将行连接到一行,并将这些类别放在带有";"分隔符的最后一列,例如:
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
我在阅读时用尝试过。。。;请务必阅读。。。done<文件,但这只是按2行读取每个文件,而不是比较每一行。还试图将类别信息保存到数组中并创建合并的类别列,但在某行脚本中,它只是停止了按我想要的方式进行解析。用awk或sed完成这项工作会很好,因为read在读取包含大量列的大文件时确实很慢,但如果有更好的方法用其他语言完成这项任务,我也可以。非常感谢!
两个答案:
外壳+sed
你可以在这种(特殊)情况下使用sed:
(嗯,太快了!我错了!
$ sed -e ':;N;s/^(([^,]+,){5})(.*)*n1/13;/;t' file.csv
)
$ sed -e ':a;$!N;s/^(([^,]+,){5})(.*)*n1/13;/;ta;P;D;$!ba' file.csv
用于检索列数(-1),也就是分隔符数:
read line <file.csv
cols="${line//,}"
cols=$[${#line}-${#cols}]
sed -e "
:a;
$!N;
s/^(([^,]+,){$cols})(.*)*n1/13;/;
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/^(.*,)([^,]*)*n1/12;/;t;P;D;$!b" file.csv
(用于在线路末端鞭打不需要的CR:
sed -e ':;$!N;s/o015//g;s/^(.*,)([^,]*)*n1/12;/;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
注意:不需要知道列数,因为这是基于最后一个逗号。