繁体   English   中英

逐行读取文件而不将整个文件加载到内存中

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM