【问题标题】:How to handle large data files using Perl?如何使用 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;

标签: perl bigdata


【解决方案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 是否不需要--即使内部优化--需要逐行读取文件?感谢您协助解决此问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-02
  • 1970-01-01
  • 2011-03-09
相关资源
最近更新 更多