分隔处理非常大的压缩JSON文件的命令的保存输出

时间:2019-03-15 23:51:14

标签: json linux csv command jq

好吧,让我们从我使用的命令行开始:

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

但是,它仅将所有内容保存在一个文件中,我认为它将保存为多个文件,每个文件都有不同的名称,因为在写入输出时日期会不断更改。

也欢迎任何其他可行的解决方案,谢谢!

3 个答案:

答案 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)

使用GNU 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"}'