perl - 扫描一个大的 .gz 文件并将它的字符串从一个已知单词(在文件中重复)中拆分出来,并将所有拆分后的字符串保存在一个 .txt 文件中
问题描述
我正在尝试编写一个 perl 脚本,在该脚本中我试图打开和读取一个 .gz 文件并将其从一个在该文件中重复多次的已知单词('.EOM')中拆分出来,并将所有拆分保存在一个.txt 或 .tmp 文件。该 .gz 文件非常非常大(以 GB 为单位)。我尝试了许多不同的方法,但每次最后都会显示以下错误。“panic:sv_setpvn 在 perl_gz1.pl 第 7 行,第 38417185 行以负 strlen 调用”这里 'per_gz1.pl' 是我的 perl 文件名,'line 101' 是我编写以下代码行的行:我的 @spl =split('.EOM',$join);
我不知道这是什么类型的错误以及如何解决它。任何人都可以帮助解决它吗?有没有其他方法可以在不出现此错误的情况下做同样的事情?提前致谢。我附上了我的完整代码。
我试过以下代码:
use strict ;
use warnings;
my $file = "/nfs/iind/disks/saptak/dsbnatrgd.scntcl.gz";
open(IN, "gzcat $file |",) or die "gunzip $file: $!";
my $join = join('',<IN>);
#print $join;
my @spl=split('.EOM',$join);
print @spl;
close IN;
use IO::Uncompress::Gunzip qw(gunzip $GunzipError) ;
my $input = "/nfs/iind/disks/cpc_disk0025/saptak/dsbnatrgd.scntcl.gz";
my $output = "NEW1.tmp";
gunzip $input => $output or die "gunzip failed: $GunzipError\n";
my $data = join("", "NEW1.tmp");
#use File::Slurp;
#my $data = read_file("NEW1.tmp");
my @spl=split(/.EOM/,$data)
and
use IO::Uncompress::Gunzip qw(gunzip $GunzipError) ;
use IO::File ;
my $input = new IO::File "</nfs/iind/disks/cpc_disk0025/saptak/dsbnatrgd.scntcl.gz" or die "Cannot open 'file1.txt.gz': $!\n" ;
my $buffer ;
gunzip $input => \$buffer or die "gunzip failed: $GunzipError\n";
print $buffer;
my @spl=split(".EOM",$buffer);
But same error is coming every time.
我希望数组@spl 每次都会在指定的单词/字符串处保存文件并输出打印它。这样我就可以继续使用这个数组@spl,但没有输出,并且输出屏幕上显示错误“panic:sv_setpvn call withnegative strlen at perl_gz1.pl line 7, line 38417185”。
解决方案
如果这是一次性工作,我可能会这样做:
zcat dsbnatrgd.scntcl.gz | perl -ne'sub newf{$n||="0000";$n++;open($fh,">","output_$n.txt")||die}$fh||newf();/(.*)\.EOM(.*)/ and print {$fh} $1 and newf() and print {$fh} $2 or print {$fh} $_'
output_nnnn.txt
每次.EOM
在某处看到an 时,这都会为您提供一个新文件。nnnn
是0001
,0002
以此类推。也可以在一行的.EOM
中间看到,然后保留之前和之后的 .EOM 以及上一个文件中的最后一个字符串和下一个文件中的第一个字符串。
oneliner解释说:
sub newf{
$n||="0000";
$n++; #increase the filename counter
open($fh,">","output_$n.txt")||die #open a new output filehandler
}
$fh||newf(); # 1st input line: create $fh file handler if it dont exists
/(.*)\.EOM(.*)/ # if the input line have a .EOM mark, grab whats before and after
and print {$fh} $1 #...and print the before on current file
and newf() #...and open new file
and print {$fh} $2 #...and print the after .EOM to the new file
or print {$fh} $_ #or if no .EOM on current line, just print it to the current output file
(或者您的意思是 .EOM 标记在 .gz 文件中未压缩?在这种情况下,.gz 文件可能无效)
您的方法不起作用的原因可能是因为输入非常大。您提到 .gz 文件是一些 GB,然后输入可能比那个大几倍。我在这里的方法不会尝试一次将所有内容都保存在内存中,因此文件大小无关紧要。
推荐阅读
- python - 什么会使此 BST 代码中的插入方法起作用?
- ios - 如何将 UIView 底部锚点向右移动到底部导航栏?
- .htaccess - 在子目录中安装 Codeigniter 4 并保持域通用 URL 结构
- c++ - 字符串 find() 函数的正确实现?
- php - symfony 提交到链接表实体
- sql - 如何使用范围内的数字生成表格
- reactjs - React bootstrap自定义导航链接活动样式不起作用
- javascript - 为什么不能在该构造函数中指定构造函数的原型?JavaScript
- python - 通过 Node.js 驱动的 Electron 应用程序与 Python shell 通信
- python - 如何在多处理池中正确保存字典