我有一个应该是JSON对象的文件,每行一个。不幸的是,在创建文件时发生了错误的通信,而JSON对象之间只有一个空格,而不是换行符。
我需要通过用} {
替换}\n{
的每个实例来解决此问题。
sed或Perl应该很容易,对吧?
sed -e "s/}\s{/}\n{/g" file.in > file.out
perl -pe "s/}\s{/}\n{/g" file.in > file.out
但是file.in
实际上是4.4 GB,这似乎导致了这两种解决方案的问题。
sed命令以中途正确的文件结束,但file.out
只有335 MB,只是输入文件的前1/10左右,在一行中间切断。它几乎就像sed刚刚在流中间退出。也许它试图将整个4.4 GB的文件加载到内存中,但是耗尽大约300MB的堆栈空间并且无声地自杀。
Perl命令错误,显示以下消息:
[1] 2904 segmentation fault perl -pe "s/}\s{/}\n{/g" file.in > file.out
我还应该尝试什么?
答案 0 :(得分:4)
与早期的解决方案不同,此解决方案处理{"x":"} {"}
。
use strict;
use warnings;
use feature qw( say );
use JSON::XS qw( );
use constant READ_SIZE => 64*1024*1024;
my $j_in = JSON::XS->new->utf8;
my $j_out = JSON::XS->new;
binmode STDIN;
binmode STDOUT, ':encoding(UTF-8)';
while (1) {
my $rv = sysread(\*STDIN, my $block, READ_SIZE);
die($!) if !defined($rv);
last if !$rv;
$j_in->incr_parse($block);
while (my $o = $j_in->incr_parse()) {
say $j_out->encode($o);
}
}
die("Bad data") if $j_in->incr_text !~ /^\s*\z/;
答案 1 :(得分:1)
perl -ple 'BEGIN{$/=qq/} {/;$\=qq/}\n{/}undef$\ if eof' <input >output
答案 2 :(得分:1)
Perl中的默认输入记录分隔符是\n
,但您可以将其更改为您想要的任何字符。对于此问题,您可以使用{
(八进制173)。
perl -0173 -pe 's/}\s{/}\n{/g' file.in > file.out
答案 3 :(得分:0)
您可以以块/块的形式读取输入并逐个处理。
use strict;
use warnings;
binmode(STDIN);
binmode(STDOUT);
my $CHUNK=0x2000; # 8kiB
my $buffer = '';
while( sysread(STDIN, $buffer, $CHUNK, length($buffer))) {
$buffer =~ s/\}\s\{/}\n{/sg;
if( length($buffer) > $CHUNK) { # More than one chunk buffered
syswrite( STDOUT, $buffer, $CHUNK); # write FIRST of buffered chunks
substr($buffer,0,$CHUNK,''); # remove FIRST of buffered chunks from buffer
}
}
syswrite( STDOUT, $buffer) if length($buffer);
答案 4 :(得分:0)
假设您的输入在其他不需要替换的上下文中不包含import matplotlib.pyplot as plt
x = [0.00001,0.001,0.01,0.1,0.5,1,5]
y = [0.945,0.885,0.893,0.9,0.996,1.25,1.19]
plt.xlim(0.00001,5)
plt.ylim(0.8,1.4)
plt.plot(x, y, marker='o', linestyle='--', color='r',
label='Square')
plt.xlabel('x')
plt.ylabel('y')
plt.title('compare')
plt.legend()
plt.show()
对,那么您需要的是:
} {
e.g。
awk -v RS='} {' '{ORS=(RT ? "}\n{" : "\n")} 1'
以上使用GNU awk进行多字符RS和RT,并且可以在任何大小的输入文件上工作,因为它不会一次将整个文件读入内存,只有每个$ printf '{foo} {bar}' | awk -v RS='} {' '{ORS=(RT ? "}\n{" : "\n")} 1'
{foo}
{bar}
- 分开的“行”一个一次。