2016-01-17 44 views
0

我的JSON对象(超过12000行)一个大文件看起来像名称:分裂一个大的JSON文件和设置输出文件

{ 
    "System": "2334", 
    "Id": "AP64531346-2016055553824", 
    "dtis": "106165099", 
    "Type": "Up", 
    ... (in total, 112 lines per record) 
} 
{ 
    "System": "873", 
    "Id": "AP24531346-20160676553824", 
    "dtis": "1261699", 
    "Type": "Up", 
    ... (in total, 112 lines per record) 
} 

我要拆小的大文件每一个文件夹都有一个入口(112行),并将每个片段的名称设置为“Id”的值,我的意思分别是例如AP64531346-2016055553824.txt和AP24531346-20160676553824。

我尝试过使用GNU Split,但是我无法将每个文件的名称设置为ID加上.txt。

split -l 112 ../bigfile.csv 

有什么建议吗?

回答

2

在两个步骤:首先你生成一般命名的文件与

split -l 112 ../bigfile.csv 

现在你有一个名为xaaxab等文件,我认为这些都是在目录中唯一的文件。现在,您可以循环过去了,提取标识并重新命名:

for file in *; do 
    newname="$(grep -m 1 -Po '(?<="Id": ")[^"]+' "$file")" 
    mv "$file" "$newname.txt" 
done 

grep -o只提取了比赛,并且采用了零宽度“向后看”来获得ID线。只有在使用Perl正则表达式引擎(-P)时才能使用浏览功能。 -m 1在第一场比赛后停止,所以当你知道第一场比赛足够好的时候,你不会浏览整个文件。

当每块没有112行时,这当然会坏掉– a proper solution会解析文件。

2

这听起来像你想把每个JSON文件放在它自己的文件中。你可以使用JSON :: XS的增量分析器来做到这一点。

use JSON::XS qw(); 

my $json = JSON::XS->utf8->new(); 

local $/ = \(1024*1024) 
while (<>) { 
    for my $obj ($json->incr_parse($_)) { 
     my $id = $obj->{Id}; 
     open(my $fh, '>', $id . ".txt") 
     or die $!; 
     print($fh $json->encode($obj)); 
    } 
} 
+2

请注意,这将导致数据中的键以不同于原来的顺序出现。如果数据实际上与描述相同,则可能比'$/=“\ n}更好\ n”; while(my $ record = <>){my $ id = $ json-> decode($ record) - > {Id};打开(我的$ fh,...)或死亡;打印$ fh $记录}'(仅在错误检查时) – ysth

+0

@ysth,正确,但按键顺序在JSON中没有意义。至于评论的其余部分,你为什么不把它作为答案发布? – ikegami

+0

与您的看起来有点太不一样 – ysth

1

的一般方法到任务(即,一种方法,使得没有关于JSON实体在输入文件中的流的假设,比它们是有效的JSON实体其他)由以下示出的“单衬里“:

jq -cr '"\(.Id)\t\(.)"' | awk -F\\t '{print $2 > "/tmp/"$1".json"}' 

这里使用了‘JSON查询’(jq)命令行处理器,其可在许多平台上。

如果您希望每个新文件是相当打印,那么你可以在第二个步骤中使用JQ对于为好,如:

ls *.json | while read f ; do jq . "$f" > "$f.tmp" && mv "$f.tmp" "$f" ; done 
+0

您知道OP发布的内容无效JSON,但评估者将多个合法的JSON片段合并到一个文件中? – andlrc

+0

你知道我在编辑帖子之前,在你评论前11个小时左右? – peak

1

JSON结构是用Perl数据结构,高度兼容快速的方式来分离记录在不同的文件可以使用eval。考虑到你json没有在值中保存“:”

local $/ = undef; 
open FILE, "Testjson.txt" or die "Couldn't open file: $!"; 
my $string = <BiGFILE>; 
close FILE; 
$string =~ s/:/,/g; 
$jsonStr = eval $string; 

foreach my $record (@{$jsonStr}) { 
print $record->{'Id'} . "\n"; 
}