2010-12-18 5 views
2

So habe ich ein Programm, das zusätzliche Zeilenumbrüche in fasta Dateien kopieren und aus dem Internet eingefügt wird. Wenn Sie nicht wissen, wie eine Fasta-Datei aussehen soll, sollte es ein Größer-als-Symbol gefolgt von etwas sein (das ist normalerweise Titelinfo), dann eine neue Zeile. Die neue Zeile sollte Ihre vollständige Sequenz (für biologische DNA oder Aminosäure) in einer Zeile enthalten und wiederholen.Umgang mit dem einsamen Wagenrücklauf als Ende der Zeile Symbol

Wie auch immer, das Problem ist, ich das Programm muß flexibel genug zu sein, mit etwas zu beschäftigen: \r, \n oder \r\n. Die chomp-Anweisung mit Unterstrichen auf beiden Seiten ist der Befehl, der die überschüssigen Zeilen im Sequenzabschnitt entfernt. Wie kann ich diesen chomp machen alle drei der Optionen (\r, \n, \r\n) loswerden? Kann ich einstellen und @linefeeds = "\r", "\n", "\r\n"; haben?

Ich habe online gelesen, ich weiß, dass dieses Thema als zuvor behandelt wurde, aber ich kann es einfach nicht scheinen, um es zu arbeiten.

Hier ist mein Code so in einer Datei zu tun:

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

Das Problem mit den Kommentaren war 1) es war eigentlich alle eine Zeile (es gab keine LF vor der zweiten #) und 2) es wurde nicht 4 Leerzeichen eingerückt. – cjm

Antwort

1

Ich neige dazu, s/[\r\n]+$//; zu verwenden. Wenn ich auch nachlaufenden Leerraum löschen möchte, verwende ich tatsächlich s/[\s\r\n]+$//;.

Von den Perl-Handbuch, wäre es ausreichend, zu sagen s/\s+$//; als \s sowohl \r und \n enthält aber Ich mag die Klarheit es formulierend.

2

Es gibt drei Fragen aus Ihrer Frage zu beantworten:

  • Technische Frage, wie aus einem String

  • Eine allgemeine Frage, wie Leerzeichen EINSCHLIESSLICH sortierten newlines abzustreifen das Dateiformat beschrieben zu verarbeiten . Ich werde eine andere Lösung vorstellen, die funktioniert, wenn die Dateigröße klein genug ist, dass Sie die ganze Datei in eine Zeichenfolge im Speicher schlürfen können.

  • Einlesen der Datei in Chunks (z. B. Zeile für Zeile), um zu vermeiden, dass die gesamte Datei in den Speicher gerieben wird.


  1. aus einer Nicht-Titelzeile Um Streifen sowohl die Leerzeichen und verschiedenen Zeilenumbrüche (zB Ihre _chomp_) Zeile können Sie tun:

    $lines =~ s/[\n\r]|\s//gs; # IIRC, \s doesn't include newlines 
    
  2. Zusätzlich , Wenn Ihre Datei klein genug ist, um alle Daten in den Speicher zu schlürfen, als eine einzelne lange Zeichenfolge in ist eine Option, können Sie (bei die Kosten von etwas langsamer Code), haben eine kürzere, hoffentlich besser lesbar Logik anstelle der Logik in Ihrem Beispielcode:

    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. Wenn jedoch die Daten groß genug ist, dass man muss es in Stücke lesen (im Falle von Text, der Chunk ist in der Regel eine Zeile), haben Sie ein Problem, mit BEIDE Ihren vorgeschlagenen Code und den Code, den ich oben gezeigt habe.

    Perl Standard Line-by-Line-Lese über <> Operator (oder readline) werden Eingabedatensatz-Separator ($/) verwenden, um zu definieren, was eine Neuer-Zeile ist, die "\ n" standardmäßig ist. Wenn Ihre Datei alle "\ r" getrennt ist, wird es als eine riesige einzelne Zeile, Bedeutung Sie werden schlürfen die Datei, ob Sie es mögen oder nicht. Natürlich wird die Änderung von $/ zu "\ r" nicht helfen.

    Leider $/ (Eingabeaufzeichnung Trennzeichen) muss eine Zeichenfolge sein und kann kein regulärer Ausdruck sein.

    Deshalb, wenn Sie unbedingt die Datei mit beliebigen Zeilenumbrüchen in Blöcken aufgrund der Größe Berücksichtigung lesen, müssen Sie Datei in festen Blockgrößen statt zeilen, und dann analysieren, einzelne Zeilen aus diesen Blöcken lesen .

    Um dies zu lesen, IIRC, können Sie $/ auf eine ganze Zahl setzen und dann readline()/<> verwenden.

    Bitte beachten Sie, dass das Modul durch cjm Antwort (PerlIO :: EOL) erwähnt tut genau den zweiten Ansatz, aber als XS-Modul implementiert wird, und somit hat es in C-Code (PerlIOEOL_get_base() Funktion Puffergröße 4k).

+0

Das Problem ist, dass aufgrund der Art des Programms und seiner Verwendung, könnte es für eine sehr kleine (~ 1000 Zeichen Textdatei) zu einer extrem langen Textdatei, ich habe auf, dass enthält 91.000 DNA-Sequenzen alle von mindestens 400 Figuren. Ein weiteres Problem ist, dass ich den Zeilenumbruch in jeder Zeile mit dem Größer-als-Symbol beibehalten möchte. Das FASTA-Dateiformat benötigt diesen Zeilenumbruch, sodass Programme, die FASTA-Dateien verwenden, feststellen können, dass sie sich außerhalb der Titelinformationen und in der Sequenz befinden. Ich denke, ich kann es als eine Einschränkung des Programms verlassen, die Datei mit dem Problem ist die am wenigsten wahrscheinliche Verwendung des Programms. – AlphaA

+0

@ user520742 - 91000 * 400 = 36,4 M Daten, soweit mein Hinterkopf schätzt, würde ich nicht erwarten, dass es so weit wie schlürfen, aber es könnte definitiv viel besser funktionieren, wenn Sie es stückchen verarbeiten. – DVK

+0

@ user520742 - es sei denn, ich habe einen Fehler, den ich nicht bemerkt habe, das Skript in Teil # 2 behält den Zeilenumbruch nach dem Titel (beginnend mit>), indem er explizit gedruckt wird ('print '$ title \ n $ rest) \ n "';) – DVK

3

Das grundlegende Problem ist, dass $/ kann nur auf einen einzelnen String gesetzt werden, und es gibt keinen Wert, den Sie es zu, dass setzen können, werden alle CR, LF und CRLF Zeilenenden entsprechen.

Aber Sie sind nicht die erste Person mit diesem Problem. Ich habe es selbst nicht ausprobiert, aber wenn Sie PerlIO::eol installieren, sollten Sie in der Lage sein, zu sagen:

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

und es wird automatisch konvertieren CR, LF oder Endungen CRLF Linie für Sie LF.

+0

+1 für CPAN-Lösung. – DVK

Verwandte Themen