2010-12-18 1 views
2

У меня есть программа, которая избавляется от лишних разрывов строк в файлах fasta, копируемых и вставленных из Интернета. Если вы не знаете, как должен выглядеть файл fasta, он должен быть больше символа, за которым следует что-либо (обычно это информация о заголовке), а затем новая строка. Новая строка должна содержать вашу полную последовательность (для биологии ДНК или аминокислоты) в одной строке и повторять.Работа с одиночным возвратом каретки как символ конца строки

В любом случае проблема заключается в том, что программа должна быть достаточно гибкой, чтобы иметь дело с чем-либо: \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

ответ

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. Однако, если данные достаточно велики, что вы должны прочитать его на кусках (в случае текста кусок обычно является одной строкой), у вас есть проблема, с BOTH вашим предлагаемым кодом и кодом, который я показал выше.

    в Perl стандартная строка за строкой чтение через <> оператора (или readline) будет использовать входной разделитель записей ($/), чтобы определить, что это символ новой строки, который «\ п» по умолчанию. Если ваш файл будет разделен на «\ r», он будет рассматриваться как гигантская одиночная строка, означает, что вы будет удалите файл в том, нравится вам это или нет. Очевидно, изменение $/ на «\ r» не поможет.

    К сожалению, $/ (разделитель входных данных) должен быть строкой и не может быть регулярным выражением.

    Поэтому, если вы абсолютно ДОЛЖНЫ прочитать файл с произвольным символом новой строки в кусках из-за рассмотрение размера, вам нужно прочитать файл в фиксированных размерах блоков вместо построчно, а затем разобрать отдельные строки из этих блоков ,

    Чтобы сделать такое чтение, IIRC, вы можете установить $/ в целое число, а затем использовать readline()/<>.

    Пожалуйста, обратите внимание, что модуль упомянутый ответ CJM в (PerlIO :: EOL) делает именно последний подход, но реализован как модуль XS и, таким образом, делает это в коде C (PerlIOEOL_get_base() функция имеет размер буфера 4k).

+0

Проблема заключается в том, что из-за характера программы и ее использования она может быть для очень маленького текстового файла (~ 1000 символов) чрезвычайно длинному текстовому файлу, который содержит 91 000 последовательностей ДНК, по меньшей мере, 400 персонажи. Другая проблема заключается в том, что я хочу поддерживать разрывы строк в каждой строке с символом больше, чем символ. Формат файла FASTA требует разрыва строки, поэтому программы, использующие файлы FASTA, могут сказать, что они не указаны в заголовке и в последовательности. Я думаю, что я могу просто оставить его в качестве ограничения программы, файл с проблемой является наименее вероятным использованием программы. – AlphaA

+0

@ user520742 - 91000 * 400 = 36.4M данных, насколько мне кажется, что касается моей задней части мозга, я бы не ожидал, что это проблема, поскольку она может быть намного лучше, если вы обработаете ее piecemail. – DVK

+0

@ user520742 - если у меня нет какой-то ошибки, которую я не заметил, скрипт в части # 2 сохранит новую строку после строки заголовка (начиная с>) благодаря явной печати ('print '$ title \ n $ rest \ n "';) – DVK

3

Основная проблема заключается в том, что $/ может быть установлен только в одной строке, и нет никакого значения вы можете установить его в том, что будет соответствовать всем CR, LF и CRLF линии окончаний.

Но вы не первый человек с этой проблемой. Я не пробовал сам, но если вы установите PerlIO::eol, вы должны быть в состоянии сказать:

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

, и он будет автоматически конвертировать CR, LF или CRLF строки окончаний к LF для вас.

+0

+1 для решения CPAN. – DVK

Смежные вопросы