[英]Reading through a file line by line without loading whole file into memory
我正在使用50 Gb MySQL导出文件,并对其执行脚本操作列表以转换为SQLite3可加载形式(我从这里得到的线索: 脚本将mysql dump sql文件转换为可以导入sqlite3的格式db )。 我尚未研究MySQL转储的结构,数据是从第三方获得的。 我可以看到它具有创建表并插入到语句中的功能,但是鉴于其大小,很难手动阅读并理解其结构。 由于大小原因,无法通过管道传输文件。 还有一个bash脚本,用于加载文件,然后逐行处理,例如
while read line
<do something>
抱怨说它的内存不足。
因此,我尝试使用awk或sed来选择每一行(两者均起作用),将该行写入文件,然后将其通过perl脚本列表。 这是我正在使用的awk脚本
$ awk -vvar="$x" 'NR==var{print;exit}' file > temp
其中x保留行号,然后通过perl命令发送temp,最后将它们附加到输出文件中。
但是,尽管最初速度很快,但是由于开始必须遍历越来越多的行,因此它很快会变慢。 大约有40,000行。
有没有人像这样工作? 有更快的方法吗?
一次只需处理一行:
while read -r line
do
echo "$line" > temp
…process temp with Perl, etc…
done < file
至少这不会表现出二次读取文件的行为,这就是您的awk
脚本所做的。 它只读取一次大文件,这是Big-O表示法的最佳性能(在恒定因子内)。
如您所说,如果这导致bash
出现问题,则应使用Perl读取每一行。 在50 GiB数据中有40,000条线,每条线大约有1¼MiB数据。 尽管可能会导致Bash问题,但这不太可能导致Perl出现任何问题。 您可以修改现有的Perl一次读取一行,也可以使用简单的包装Perl脚本来完成上述Bash脚本的工作。
wrapper.pl
假设您当前的处理脚本称为script.pl
:
#!/usr/bin/env perl
use strict;
use warnings;
my $file = "temp";
while (<>)
{
open my $fh, ">", $file or die;
print $fh $_;
close $fh;
system "perl", "script.pl", $file;
}
未经测试的代码
调用:
perl wrapper.pl <file >output
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.