根据指定的行数拆分CSV文件
2021年4月17日大约 2 分钟
CSV文件以纯文本形式存储表格数据。不同于Excel文件复杂的内容格式,纯文本文件可以非常方便地使用Shell命令处理。
在最近的工作中遇到一个问题:客户导出的用户数据有60w条之多,全部保存在一个CSV文件中。要导入系统中遇到了几个问题:
- 由于考虑不周,在导入用户的脚本中没有按行读取CSV文件,而是一次性全部加载到内存中循环处理。在这样的情况下就必须要考虑大数据量导入时内存溢出的问题。
- 每导入一个用户系统都要做触发相关事件等额外操作。这就导致如果是一个文件从头到尾导入,速度会非常慢,时间过长无法接受。期望可以使用多个文件并行导入。
- 期望在导入过程中某一条数据出错导致脚本崩溃时,可以尽可能小范围排查数据,也要尽可能减少重试时检查已导入的数据。
综合考虑,我们需要把这个巨大的CSV拆分为小文件,每个文件2w行且第一行保留表头。
使用split
命令拆分文件
split
命令可以将一个大文件按文件大小或行数拆分为多个小文件。
- 新建一个
splitCsv.sh
文件,粘贴下面的代码后保存。
#!/bin/bash
HEADER=$(head -1 $1)
if [ -n "$2" ]; then
CHUNK=$2
else
CHUNK=1000
fi
tail -n +2 $1 | split -l $CHUNK - $1_split_
for i in $1_split_*; do
sed -i -e "1i$HEADER" "$i"
done
- 给
splitCsv.sh
添加可执行权限。
chmod u+x splitCsv.sh
- 拆分CSV文件。
./splitCsv.sh User.csv 20000
为文件批量添加.csv
后缀名
使用split
命令拆分文件后每个分片文件会被加上aa
、ab
、ac
这样的序号后缀(也可以通过加上-d
参数指定为数字后缀),如User.csv_split_aa
。我们期望拆分出来的每个文件都有相同的.csv
后缀。
执行下面的命令,为User.csv_split_
开头的文件加上.csv
后缀名。
ls User.csv_split_* | xargs -t -i mv {} {}.csv