Работа с возвратом одиночной каретки в качестве символа конца строки - PullRequest
3 голосов
/ 18 декабря 2010

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

В любом случае, проблема в том, что мне нужна программа, чтобы быть достаточно гибкой, чтобы справиться с чем-либо: \r, \n или \r\n.Оператор chomp с подчеркиванием с обеих сторон - это команда, которая удаляет лишние строки в части последовательности.Как я могу заставить этот chomp избавиться от всех трех опций (\r, \n, \r\n)?Могу ли я установить $\ = @linefeeds и иметь @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;
            }
        }
    }
}

Ответы [ 3 ]

3 голосов
/ 18 декабря 2010

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

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

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

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

2 голосов
/ 18 декабря 2010

На ваш вопрос следует ответить на три вопроса:

  • Технический вопрос о том, как убрать пробел, ВКЛЮЧАЯ разные переводы строк:

  • Общий вопрос о том, как обрабатывать описанный формат файла.Я представлю другое решение, которое работает, если размер файла достаточно мал, чтобы вы могли записать весь файл в строку в памяти.

  • Чтение в файле кусками (например, строка(by-line), чтобы избежать потери всего файла в памяти.


  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).

2 голосов
/ 18 декабря 2010

Я склонен использовать s/[\r\n]+$//;.Когда я также хочу удалить конечные пробелы, я на самом деле использую s/[\s\r\n]+$//;.

Из руководств по Perl было бы достаточно сказать s/\s+$//;, поскольку \s включает в себя \r и \n, ноМне нравится ясность изложения.

...