拆分大的json文件并设置输出文件的名称

时间:2016-01-17 22:12:21

标签: python json perl shell awk

我有一个大型JSON对象文件(超过12000行),如下所示:

split -l 112 ../bigfile.csv 

我想将大文件分成小文件,每个文件有一个入口(112行),并将每个文件的名称设置为" Id"的值,我的意思是例如AP64531346-2016055553824 .txt和AP24531346-20160676553824分别。

我尝试使用GNU Split但我无法将每个文件的名称设置为Id plus .txt。

"Error: Invalid domain for site key"

有什么建议吗?

4 个答案:

答案 0 :(得分:2)

分两步:首先使用

生成一般命名的文件
split -l 112 ../bigfile.csv

现在你有了xaaxab等文件。我认为这些是目录中的唯一文件。现在你可以遍历它们,提取Id并重命名它们:

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

grep -o仅提取匹配项,并使用零宽度&#34; look-behind&#34;得到Id行。仅在使用Perl正则表达式引擎(-P)时才能查看。 -m 1在第一场比赛后停止,因此当您知道第一场比赛足够好时,您就不会浏览整个文件。

当每个块没有112行时,这当然会严重破坏 - proper solution会解析文件。

答案 1 :(得分: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 :(得分:1)

该任务的一般方法(即,不对输入文件中的JSON实体流做任何假设的方法,除了它们是有效的JSON实体之外)由以下&#34; one-liner& #34;:

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

这使用&#34; JSON查询&#34; (jq)命令行处理器,可在许多平台上使用。

如果您希望每个新文件都是漂亮的,那么您可以在第二步中使用jq,例如:

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

答案 3 :(得分: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";
}