好吧,让我们从我使用的命令行开始:
curl --silent http://example.com/json.gz | pigz -dc | jq -r '[.name, .value] | @csv' > data.csv
CURL将下载压缩的11.6 GB的JSON文件,pigz
将对其进行解压缩并将所有处理后的输出写入stdout,jq
将读取JSON并将输出另存为csv文件。
问题是,保存为data.csv的输出非常大,毕竟我仍然需要使用PHP脚本分析此数据并将其以特殊格式插入到MYSQL中(数据的大小会很小,然后)
但是,我的服务器上只有不到60 GB的可用空间,即使我无法解压缩全部数据并将其保存到CSV文件中。
所以,我有个主意,如果我能够将输出保存到具有不同名称(例如,名称是当前日期或时间戳记)的分离文件中,那么我可以运行PHP脚本来处理每个.csv将它们保存为文件,然后将数据保存到db,然后删除文件以释放空间,不确定这是否是最好的方法,但是至少我正在尝试使其工作。
因此,我将命令行修改为:
curl --silent http://example.com/json.gz | pigz -dc | jq -r '[.name, .value] | @csv' > `date +"%S-%M-%d-%m-%Y"`_data.csv
但是,它仅将所有内容保存在一个文件中,我认为它将保存为多个文件,每个文件都有不同的名称,因为在写入输出时日期会不断更改。
也欢迎任何其他可行的解决方案,谢谢!
答案 0 :(得分:3)
使用split
命令,请参阅man-page
简单示例(10MB至STDOUT):
# dd if=/dev/zero bs=1M count=10 | split - --bytes=1M -d -a3 out
输出文件(从STDIN读取的10个文件,大小为1MB):
# stat -c "%s %n" out00*
1048576 out000
1048576 out001
1048576 out002
1048576 out003
1048576 out004
1048576 out005
1048576 out006
1048576 out007
1048576 out008
1048576 out009
或使用split --bytes=1M -d -a3 out out
输出:
# stat -c "%s %n" out*
10485760 out
1048576 out000
1048576 out001
1048576 out002
1048576 out003
1048576 out004
1048576 out005
1048576 out006
1048576 out007
1048576 out008
1048576 out009
答案 1 :(得分:3)
split --filter
节省空间 POSIX split
从其输入创建输出文件,因此需要大量可用空间来存储它们(整个未压缩输入的大小加上一些开销)。
但是,split
的GNU版本具有一个额外的--filter
选项,该选项可以在更少的空间中处理单个数据块,因为它不需要创建任何临时文件:
| split -l $NUMLINES --filter='shell_command'
您可以将其视为xargs -n $NUMLINES command
,除了将数据传递给stdin而不是将其作为命令行参数。
例如,要输出/ etc / passwd的每组(最多)7行的md5sum,然后输出已处理的块数:
</etc/passwd split -l7 --filter='md5sum|tee /dev/tty' |\
{ echo Processed $(wc -l) chunks; }
要将命令修改为一次可处理10000行,可以执行以下操作:
curl -L --silent "$URL" |\
pigz -dc |\
jq -r '[.name, .value] | @csv' |\
split -l 10000 --filter='save2db.php'
您的过滤器命令save2db.php
应该从标准输入中读取。
如果您希望将其从实际文件中读取,则可以执行以下操作:
... |\
split -l 10000 --filter='cat >TMPFILE; save2db.php TMPFILE';
rm TMPFILE
警告::您需要确保在行边界上分割csv文件是安全的。某些csv文件包含带有嵌入式文字换行符的字段。如果中场分开,它们可能变得畸形。
答案 2 :(得分:1)
我建议使用诸如awk
之类的程序进行分区,例如像这样:
jq -rc '[.id, .value] | @csv' |
awk -v NUM 100000 '{n++; print > "out." int((n+NUM)/NUM) ".csv"}'