Richtig erkennen line-Endungen eine Datei in Perl?
Problem: ich habe Daten (meist im CSV-format) erzeugt, die auf Windows-und *nix und verarbeitet werden, meistens auf *nix. Windows verwendet CRLF für die Zeilenenden und Unix verwendet LF. Für eine bestimmte Datei, die ich weiß nicht, ob man windows oder *nix-Zeilenenden. Bis jetzt, ich habe das schreiben etwas wie dieses zu handhaben ist der Unterschied:
while (<$fh>){
tr/\r\n//d;
my @fields = split /,/, $_;
# ...
}
Auf *nix \n Teil entspricht scharrt, und zusätzlich entledigt \r (CR) wenn es ein windows-produziert-Datei.
Aber jetzt will ich Text::CSV_XS b/c ich fange an, seltsamer Daten-Dateien mit zitiert Daten, die potenziell mit eingebetteten Zeilenumbrüche, etc. Um dieses Modul zu Lesen wie Dateien, Text::CSV_XS::getline() benötigt die Angabe der end-of-line-Zeichen. (Ich kann nicht Lesen, jede Zeile wie oben, tr/\n\ \ r//d und Sie analysieren es mit Text::CSV b/c, dass wäre nicht mit eingebetteten Zeilenumbrüche richtig). Wie kann ich richtig erkennen, ob eine beliebige Datei benutzt windows oder *nix-Stil Zeilenenden, so kann ich sagen, Text::CSV_XS::eol (), wie chomp()?
Konnte ich nicht finden, ein Modul auf CPAN, die einfach erkennt Zeilenenden. Ich will nicht zuerst konvertieren alle meine datafiles über dos2unix, b/c die Dateien sind sehr groß (Hunderte von gigabytes), und verbringen 10+ Minuten für jede Datei, befassen sich mit etwas, das so einfach scheint albern. Ich dachte über das schreiben einer Funktion, die liest die ersten paar hundert bytes einer Datei und zählt LF vs CRLF, aber ich weigere mich zu glauben, dass dies nicht eine bessere Lösung.
Hilfe?
Hinweis: alle Dateien sind entweder vollständig von windows-Zeilenenden oder *nix-Endungen, das heißt, Sie sind nicht beide gemischt in einer einzigen Datei.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Konnte Sie nur öffnen Sie die Datei mit der
:crlf
PerlIO-Schicht und dann sagen Text::CSV_XS zu verwenden\n
als Zeilenende Zeichen. Dies wird stillschweigend anzeigen alle CR/LF-Paare-single-line-feeds, aber das ist vermutlich das, was Sie wollen.Seit Perl 5.10 können Sie verwenden, um zu überprüfen Allgemeine Zeilenenden,
Es sollte in allen Fällen funktionieren, beide *nix und Windows.
Lesen in der ersten Zeile jeder Datei, suchen Sie auf den letzten, aber ein Zeichen. Wenn es
\r
, die Datei kommt von Windows, wenn nicht, es ist *nix. Dannseek
zu Beginn und starten Sie die Bearbeitung.Wenn es möglich ist, für eine Datei mit gemischten Zeilenenden (z.B. andere Art für eingebettete Zeilenumbrüche), können Sie nur erraten.
In der Theorie Zeilenenden nicht zuverlässig ermittelt werden: Ist diese Datei eine einzelne Zeile mit DOS-Zeilenenden mit embeded
\n
s oder ist das ein paar Zeilen mit ein paar streunenden\r
Zeichen am Ende der Zeilen?versus
Wenn die statistische Analyse ist nicht eine option, da es zu ungenau und zu teuer (es braucht Zeit, um zu Scannen, so große Dateien), Sie haben tatsächlich wissen was die Codierung ist.
Wäre es am besten, mit Angabe der genauen Datei-format, wenn Sie die Kontrolle über die Erstellung von Bewerbungsunterlagen oder eine Art von Metadaten zu verfolgen, die Plattform die Daten erzeugt wurde.
In Perl, der Charakter
\n
darstellt, ist von der locale abhängig:\n
/\012
auf *nix Maschinen,\r
/\015
auf alten Macs und die Reihenfolge\r\n
/\015\012
auf DOS-Nachfolger aka Windows. So zu tun, zuverlässige Bearbeitung, sollten Sie die oktale Werte.Können Sie die
PERLIO
variable. Dies hat den Vorteil, dass Sie nicht mit ändern Sie den Quelltext Ihres Skripts abhängig von der Plattform.Wenn man sich mit DOS-text-Dateien, setzen Sie die Umgebungsvariable
PERLIO
zu:unix:crlf
:Wenn Sie vor allem Umgang mit DOS-text-Dateien (z.B. Cygwin), könnte Sie dies in Ihrem
.bashrc
:(Ich denke, der Wert sollte die Standardeinstellung für
PERLIO
auf Cygwin, aber scheinbar ist es nicht.)