分割一个 60GB 的平面文件,记录偶尔跨越多行

分割一个 60GB 的平面文件,记录偶尔跨越多行

手动输入数据会使数据库被包含多个换行符的记录污染。对于只有一列的 60GB 巨大平面文件中开头和结尾处用双引号分隔的良好记录,它们应该始终只跨越一行,如下所示:

“现在可以获得许多线粒体、许多原核生物和一些核基因组的完整序列。”

对于不良记录,它们跨越无限数量的多行,如下所示:

“当前吸烟与高风险呈强烈负相关。

调整伴随风险因素后的模式。相对于从不

吸烟者,当前吸烟者患高风险的可能性明显降低

图案。 ”

这些多行记录禁止 UNIX 命令进行下游文件分割splitsplit无法智能地将这些多行识别为单个记录,这可能导致将单个记录拆分为单独的文件。下面的 Perl 太慢了,无法在分割之前先合并这个大文件的坏记录行,因为等待超过 2 小时后 $count 无法打印。

$file=$ARGV[0];
open(INFO, $file) or die("Could not open $file.");
open(OUT, ">out") or die("Could not open $file.");

$mergedline = "";
$count=0;
foreach $line (<INFO>)  {
    print $count++;
    if ($line =~ /^".*"\n$/) {
                print OUT $line;
                $mergedline = "";
                next;
        } elsif ($line =~ /"\n$/) {
                print OUT $mergedline;
                $mergedline = "";
                next;
        } else {
                chomp $line;
                $mergedline .= $line;
        }
}
close(INFO);

有什么方便的 UNIX 命令可以解决这个问题,使输出文件“干净”,只有单行记录可以处理split

sed似乎是一个选项,但以下帖子都没有回答这个问题:

https://stackoverflow.com/questions/15758814/turning-multiple-lines-into-one-line-with-comma-separated-perl-sed-awk

https://stackoverflow.com/questions/11290616/sed-conditional-merge-of-multiple-lines

http://www.unix.com/shell-programming-and-scripting/80633-sed-combining-multiple-lines-into-one.html

因为他们发帖的模式太有规律、太恒定了。

答案1

仅用于sed连接分割线

sed ':a
/".*"$/b
N;s/\n/ /;ba' input >> output

在我的系统上处理一个 10 MB 的文件需要 6 秒。对于 60 GB,这将是 10 小时。

bbe有点快

bbe -b '/"/:/"/' -o output -e 'y/\n/ /' input

但仍然需要 4 秒。

恐怕这些脚本语言不是在极大文件上表现良好的工具。写一个小程序怎么样C

答案2

使用示例gawk

awk 'BEGIN {RS = "\"\n"} {++n; print $0"\""> n".txt"}' input

input这表示按照任意顺序分割文件,"后跟换行符 ( \n)。这将忽略不立即跟在引号后面的换行符,从而保留多行记录。在此示例中,输出写入文本文件,但如果删除该> n".txt"部分,则可以将记录发送到管道。

答案3

Perl由于for使用循环来读取文件,因此您的速度很慢。您确实应该使用while循环,因为for循环一次性将整个文件加载到内存中。这就是为什么打印 $count 需要很长时间的原因。

perl -ne '
   print,next if /^".*"$/m or /"$/m;
   chomp, $_ .= <>, redo unless eof;
' gene.data

相关内容