Text einlesen unter Linux und Win*

02/09/2009 - 11:07 von Robert Berghaus | Report spam
Hallo

Ein Programm, welches zur Zeit unter Windows làuft, habe ich unter
Linux laufen lassen und hierbei das Zeilenende ($/) für chomp auf
CRLF gesetzt, da die Dateien, welche eingelesen werden, mit CRLF
versehen sind.
Jetzt habe ich das geànderte Programm wieder unter Windows laufen
lassen und mußte dabei feststellen, daß das Einlesen der Dateien
nicht mehr funktioniert.

Zum Testen habe ich dann unten stehendes Programm erstellt, einmal
mit 0x0a als Zeilenende unter Linux und einmal mit 0x0d0a unter
Windows. Bei der Windowsversion ist $/ auf 0x0d0a gesetzt.
Wenn ich die Versionen unter Linux laufen lasse, sehe ich bei dem
print vor chomp 0x0a bzw. 0x0d0a. Unter Windows verhàlt sich das
unerwartet anders.
Bei der Windowsversion des Programmes (Zeilentrenner ist CRLF und
$/=LF) wird beim Einlesen (@aFeld = <DATA>) schon das CR entfernt
und nach dem chomp auch das LF. Es werden 2 Zeilen eingelesen.
Mit $/=CRLF wird ebenfalls das CR entfernt, es wird aber nur eine
Zeile eingelesen und chomp àndert nichts mehr (es ist ja auch kein
CRLF mehr da!).
Wenn ich vor dem Einlesen binmode(DATA) benutze, verhàlt sich das
Win-Programm genau wie das Linux Programm; nach dem Einlesen sehe
ich CRLF und nach dem chomp ist das weg.

Ist das jetzt ein Bug oder ein Feature?
Die Windowsversion habe ich unter Windows mit ActiveState Perl
getestet und unter OS2 mit dem normalen Port. Beides verhàlt sich
identisch. Ich vermute, daß ein DOS Perl sich ebenso verhalten
würde, da auch hier der normale Zeilentrenner CRLF ist.

Grüße aus dem Bergischen Land
Robert


<Programm>
#!/usr/bin/perl -w

use strict;

$/ = "\x0d\x0a";
#$/ = "\x0a";
my @aFeld = <DATA>;
foreach (@aFeld) { print "$_#" . join('', unpack('H*', $_)) . ""; }
chomp(@aFeld);

print "Zeilentrenner ist (" . join('', unpack('H*', $/)) . ")";
print scalar @aFeld . " Zeilen";

foreach (@aFeld) { print "$_#" . join('', unpack('H*', $_)) . ""; }

__DATA__
Zeile 1
Zeile 2
</Programm>
 

Lesen sie die antworten

#1 Wolf Behrenhoff
02/09/2009 - 11:56 | Warnen spam
Robert Berghaus schrieb:
Wenn ich vor dem Einlesen binmode(DATA) benutze, verhàlt sich das
Win-Programm genau wie das Linux Programm; nach dem Einlesen sehe
ich CRLF und nach dem chomp ist das weg.

Ist das jetzt ein Bug oder ein Feature?



Das ist ein Feature.

Wenn du dich jeweils an die Konventionen hàltst, also unter Windows CRLF
und unter Linux nur LF als Zeilenende nimmst, dann funktioniert den
Script nàmlich jeweils korrekt - du kannst also immer "" schreiben,
wenn du einen Zeilenumbruch meinst. Wenn du Dateien im Textmodus
öffnest, konvertiert das IO-Layer beim Einlesen bzw. beim Schreiben
automatisch auf das richtige Zeilenende.

Nun willst du aber eine Datei mit "falschen" Zeilenenden unter Linux
laden, wo die Ersetzung von CR natürlich nicht stattfindet. Daher bist
du schon selbst auf die Lösung gekommen: einfach die Datei im raw-Modus
öffnen und $/ auf den Zeilentrenner setzen und dann mit chomp den
Trenner jeweils entfernen.

Eine vielleicht bessere Lösung ist, dass du Perl gleich beim Einlesen
mitteilst, dass du eine Datei mit CRLF-Umbrüchen liest:

open my $file, "<:crlf", "dateiname" or die $!;

Und dann einfach vergessen, dass da CRLF drin ist! Dann musst du auch
nicht mit $/ rumhantieren.

Schau dir mal perldoc PerlIO an.

- Wolf

Ähnliche fragen