如何使用 Perl 处理大数据文件?

Posted

技术标签:

【中文标题】如何使用 Perl 处理大数据文件?【英文标题】:How to handle large data files using Perl? 【发布时间】:2012-05-23 16:11:13 【问题描述】:

我有一个 300GB 的文件,我需要一些如下所示的行。从下面显示的行中,我只需要以>miR 开头的行。

我已经编写了一个 Perl 程序,它实际上打印了我想要的输出,但是当我将相同的代码应用于更大的文件(如下所示的类似行)高达 300 GB 的数据时,如何进行呢?是否有任何替代方法可以在此代码中实现,因为如果代码运行,它就会被杀死。

#!/usr/bin/perl -w
$len=@ARGV;
if($len eq 0)
    print "Give file \n";
    exit;

$file=$ARGV[0];
open(FH,$file) || die "cant open file\n";
@lines=<FH>;
close FH;
while ($line=<FH>)
    chomp $line;
    if ($line =~ /^>miR/)
        $_=$line;
        s/>//g && s/,//g;
        print "$_\n";
        if($_=~ /(\S+)\s(\S+)\s(\S+)\s(\S+)\s(\S+)\s(\S+)\s(\S+)\s(\S+)\s(\S+)\s(\S+)\s(\S+)/)
            print $1,"\t",$2,"\t",$7,"\t",$3,"\n";
        

.

Forward:    Score: 124.000000  Q:2 to 18  R:1 to 20 Align Len (17) (64.71%) (82.35%)

   Query:    3' gaauAUUCGUUAG-AAUGGUAa 5'
                    |:: :|||| || |||| 
   Ref:      5' --ctTGGTTAATCATTCCCATt 3'

   Energy:  -10.480000 kCal/Mol

Scores for this hit:
>miR844a    AT2G33810,  124.00  -10.48  2 18    1 20    17  64.71%  82.35%


   Forward: Score: 120.000000  Q:2 to 19  R:289 to 308 Align Len (17) (64.71%) (76.47%)

   Query:    3' gaaUAUUCGUUAGAAUGGUAa 5'
                   ||::| ||  || |||| 
   Ref:      5' ttgATGGG-AAAATTTCCATt 3'

   Energy:  -9.850000 kCal/Mol

Scores for this hit:
>miR844a    AT2G33810,  120.00  -9.85   2 19    289 308 17  64.71%  76.47%


   Forward: Score: 118.000000  Q:2 to 19  R:483 to 503 Align Len (17) (64.71%) (82.35%)

   Query:    3' gaaUAUUCGUUAGAAUGGUAa 5'
                   :||:  |||| ||:||| 
   Ref:      5' gggGTAGAAAATCATATCATa 3'

【问题讨论】:

请正确格式化您的问题。使用正确的语法和大小写。字符串“i”不是英语单词。 前几行是我用过的代码,后面几行是300GB文件的几行数据.. 我不知道“带有 >miR 的线条”是什么。 @tarakaramji 问题中的源代码看起来很混乱,就像缺少换行符一样-也许您可以将其格式化为可读?向我们展示您的最佳猜测,而不是注释掉的代码。 (@lines= 看起来很可疑,因为它值得。) 另外,use strict;use warnings; 【参考方案1】:

我们可以设置local $/ = '&gt;'(作为记录分隔符),然后使用如下:

use Modern::Perl;


    local $/ = '>';
    while (<DATA>)
        next if !/^miR/;
        s/,//g;
        my($var0, $var1, $var2, $var6) = (split ' ', $_, 8)[0..2, 6];
        say"$var0,\t$var1,\t$var6,\t$var2";
    



__DATA__
>miR844a    AT2G33810,  124.00  -10.48  2 18    1 20    17  64.71%  82.35%


   Forward: Score: 120.000000  Q:2 to 19  R:289 to 308 Align Len (17) (64.71%) (76.47%)

   Query:    3' gaaUAUUCGUUAGAAUGGUAa 5'
                   ||::| ||  || |||| 
   Ref:      5' ttgATGGG-AAAATTTCCATt 3'

   Energy:  -9.850000 kCal/Mol

Scores for this hit:
>moR844a    AT2G33810,  120.00  -9.85   2 19    289 308 17  64.71%  76.47%


   Forward: Score: 118.000000  Q:2 to 19  R:483 to 503 Align Len (17) (64.71%) (82.35%)

   Query:    3' gaaUAUUCGUUAGAAUGGUAa 5'
                   :||:  |||| ||:||| 
   Ref:      5' gggGTAGAAAATCATATCATa 3'
>miR844a    AT2G33810,  120.00  -9.85   2 19    289 308 17  64.71%  76.47%


   Forward: Score: 118.000000  Q:2 to 19  R:483 to 503 Align Len (17) (64.71%) (82.35%)

   Query:    3' gaaUAUUCGUUAGAAUGGUAa 5'
                   :||:  |||| ||:||| 
   Ref:      5' gggGTAGAAAATCATATCATa 3'

输出:

miR844a,    AT2G33810,  1,  124.00
miR844a,    AT2G33810,  289,    120.00

如果当前记录不以“miR”开头,则请求下一条记录(以“>”开头的记录),否则删除任何逗号,然后拆分记录以获得您所追求的值(来自您的正则表达式)。

希望这会有所帮助!

【讨论】:

您的代码将整个段落拆分为四十多个字段。通常这无关紧要,但对于 300GB 的文件,我建议改为 split ' ', $_, 8 @Borodin - 是的,你说的很对;很好的建议。进行了编辑。谢谢。 @kenosis:是否有任何选项可以破坏文件并在代码本身中处理它们????因为代码运行缓慢... @tarakaramji:您可以使用grep&gt;miR 行提取到单独的文件中,然后在其上运行程序。我还建议您将循环的最后两行替换为print join("\t", (split ' ', $_, 8)[0,1,6,2]), "\n"; @Borodin:print join 的建议肯定会比我的原始代码节省时间。这是一个很好的修改。但是,与使用$/ = '&gt;' 相比,grep 是否不需要--即使内部优化--需要逐行读取文件?感谢您协助解决此问题。

以上是关于如何使用 Perl 处理大数据文件?的主要内容,如果未能解决你的问题,请参考以下文章

perl处理fasta文件

指定要处理的文件到 Perl 单行

如何在 Perl 中读取和写入大缓冲区到进程 stdin/stdout/stderr?

如何使用 Perl 在文件中查找扩展的 ASCII 字符?

如何有效地清空 Perl DBM 文件?

我的 perl 脚本如何调用和执行并后处理它