2010-12-18 52 views
2

所以我有一个程序,可以从fasta文件中复制和粘贴多余的换行符。如果你不知道fasta文件应该是什么样子,它应该是一个比符号更大的符号,然后是任何东西(这通常是标题信息),然后是新行。新的行应包含完整的序列(用于生物DNA或氨基酸),并重复。处理单行回车作为行尾符号

无论如何,问题是我需要的程序要足够灵活来处理任何事情:\r,\n\r\n。在任何一侧带有下划线的chomp语句都是删除序列部分中多余行的命令。我该如何使这个chomp摆脱所有三个选项(\r,\n\r\n)?我可以设置并且有@linefeeds = "\r", "\n", "\r\n";

我已经在网上阅读过,我知道这个话题已经被覆盖过,但我似乎无法让它工作。

这里是我的代码在一个文件中这样做:

print "Please enter file name, using the full pathway, to save your cleaned fasta file to:\n"; 
chomp($new_file = <STDIN>); 
open(New_File, "+>$new_file") or die "Couldn't create file. Check permissions on location.\n"; 

#process the file line by line, chomping all lines that do not contain "greater than" and 
#removing all white space from lines that do not contain "greater than" 

my $firstline = 1; 
while (my $lines = <FASTA>) { 
    foreach ($lines) { 
     if (!/>/) { 
      _chomp($lines);_ 
      $lines =~ s/ //g; 
      print New_File "$lines"; 
     } else { 
      if ($firstline == 1) { 
       print New_File "$lines"; 
       $firstline = 0; 
      } else { 
       print New_File "\n$lines"; 
       next; 
      } 
     } 
    } 
} 
+0

评论的问题是1)它实际上是全部一行(在第二个#之前没有LF)和2)它没有缩进4个空格。 – cjm 2010-12-18 09:01:48

回答

1

我倾向于使用s/[\r\n]+$//;。当我也想删除尾随空白时,我实际上使用s/[\s\r\n]+$//;

从Perl的手册,这将足以说s/\s+$//;\s包括\r\n但我喜欢拼写出来的清晰度。

2

有三个问题,从你的问题来解决:

  • 如何剥离空白包括来自于字符串

  • 如何处理所描述的文件格式的一般问题什锦换行符技术问题。我将介绍一种不同的解决方案,如果文件大小足够小,可以将整个文件写入内存中的字符串,则该解决方案将起作用。

  • 以块为单位(例如逐行)读取文件,以避免将整个文件拖入内存中。


  1. 要从非标题行剥离两个空格和各种换行符(例如你的_chomp_)线,你可以这样做:

    $lines =~ s/[\n\r]|\s//gs; # IIRC, \s doesn't include newlines 
    
  2. 另外,如果你的文件足够小,把它全部存入内存,因为单个长字符串是一个选项,你可以(在稍微慢一些代码的成本),有一个较短的,希望更多的可读逻辑,而不是逻辑的示例代码:

    my @lines = split(/(\015|\012|\015\012)>/, $text); # Split on ">" first line char 
    foreach my $line (@lines) { 
        my ($title, $rest) = ($line =~ /^(>[^\n\r]+)[\n\r](.*)$/s); 
        $rest =~ s/[\n\r]|\s//gs; # Strip whitespace AND newlines. 
        print New_File "$title\n$rest\n"; 
    } 
    
  3. 但是,如果数据足够大,你必须在成批读它(在文本的情况下,块通常是一行),你有一个问题,同时你提出的代码和上面显示的代码。

    Perl的标准线由行通过<>运营商(或readline)读数将使用输入记录分隔符($/)来定义什么是换行, 这是“\ n”默认情况下。如果你的文件全部是“\ r”分开的话,它将被视为一个巨大的单行, 这意味着你不管你喜不喜欢它。显然,将$/更改为“\ r”将无济于事。

    不幸的是,$/(输入记录分隔符)必须是字符串,不能是正则表达式。

    因此,如果你绝对必须阅读与大块由于大小考虑任意换行的文件, 你需要阅读文件中的固定块大小,而不是由线行,然后解析出从这些块单独的线。

    要做这样的阅读,IIRC,您可以将$/设置为一个整数,然后使用readline()/<>

    请注意,由cjm的答案(PerlIO :: eol)提到的模块完全采用后一种方法,但它作为XS模块实现,因此以C代码(PerlIOEOL_get_base()函数具有4k缓冲区大小)实现。

+0

问题是由于程序的性质及其用途,它可能是一个非常小的(〜1000个字符的文本文件)到一个非常长的文本文件,我已经包含91000个DNA序列,至少有400个字符。另一个问题是,我想在每个符号大于一行的行中保留换行符。 FASTA文件格式需要换行符,所以使用FASTA文件的程序可以告诉他们已经不在标题信息和序列中。我想我可能会把它作为程序的限制,具有问题的文件是程序使用最少的文件。 – AlphaA 2010-12-18 20:33:08

+0

@ user520742 - 91000 * 400 = 36.4M的数据,据我估计,我不会期望它存在的问题,尽管如此,如果您处理单件邮件,它肯定可能会更好。 – DVK 2010-12-18 23:00:13

+0

@ user520742 - 除非我有一些我没有注意到的bug,否则第2部分的脚本将通过明确地打印它('print'$ title \ n $ rest)来保留标题(以>开头)后的换行符\ n“';) – DVK 2010-12-18 23:02:13

3

最根本的问题是,$/只能设置为一个字符串,而且也没有价值,你可以将其设置为将匹配所有CR,LF,并CRLF行结束。

但是,你不是第一个有这个问题的人。我还没有尝试过自己,但如果你安装PerlIO::eol,你应该能够说:

binmode FASTA, ":raw:eol(LF)"; 

,它会自动地转换CR,LF或CRLF行结束LF你。

+0

用于CPAN解决方案。 – DVK 2010-12-18 22:57:38