2010-12-18 31 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