[LinuxOB] CSV - Datei

Rolf Kiessling r_kiessling at gmx.de
Mo Sep 12 16:25:19 CEST 2005


At 14:24 11.09.2005, you wrote:
>On 2005.09.11 13:26, Michael Gisbers wrote:
> > Am Mittwoch, 7. September 2005 19:23 schrieb Daniel Dombrowski:
>[...]
> > > Auch wenn es bestimmt kürzer geht, so geht es auf jeden Fall auch
> > > so:
> > >
> > > perl -e 'while(<>) { if ($_ =~ s/^\///) {chomp $l} print $l; $l =
> > > $_} print $l'
> > >
> > > Datei auf STDIN reinschicken und Ergebnis auf STDOUT in Empfang
> > nehmen.
> >
> > Schön!!! Aber sehr kryptisch. Könntest Du das Script mal erklären?
>
>Also grundsätzlich ersteinmal: perl -e '...' bedeuted, dass das Perl-
>Script direkt mit auf der Kommandozeile mitgeliefert wird. Man hätte es
>natürlich auch in eine Datei schreiben können.
>
>Ich habe das Skript erstmal ein wenig entkryptisiert und so umgebaut,
>dass es auch einem "use strict" genügt:
>
>my $last = "";
>while(my $line = <STDIN>)
>{
>  if ($line =~ /^\//)
>  {
>   $line =~ s/^\///;
>   chomp $last;
>  }
>  print $last;
>  $last = $line;
>}
>print $last;
>
>Das Script liest die Eingabe Zeile für Zeile ein. Dadurch, dass das
>Einlesen direkt als while-Bedingung gemacht wird, terminiert die
>Schleife, wenn das Eingabeende erreicht ist. Dabei wird als erstes mit
>dem regulären Ausdruck /^\// geprüft, ob die Zeile mit einem / beginnt.
>Die umrahmenden / leiten den Regulären Ausdruch ein (und beenden ihn),
>das ^ steht für den Zeilenanfang und das \/ ist der /, der mit einem \
>escaped werden muss, damit man ihn von den Rand-Slashes unterscheiden
>kann. Beginnt die Zeile mit einem /, wird dieser über den
>Substitutionsausdruck s/^\/// entfernt (dort ist wieder der reguläre
>Ausdruck von oben enthalten; das s sagt, dass ersetzt werden soll und
>der letzte Slash trennt das zu Ersetzende ab, hier ein leerer String.
>Der eigentliche Aufbau ist folgender: s/das hier ersetzen/durch das
>hier/optionen für die Ersetzung).
>
>Außerdem wird mit chomp $last der Zeilenumbruch der letzten Zeile
>entfernt. Danach wird mit print $last die letzte Zeile ausgegeben (ggf.
>eben ohne Zeilenumbruch am Ende, so das die nächste Zeile dann
>angehängt wird). Dann wird die aktuelle Zeile die letzte Zeile. Ganz am
>Ende muss dann noch einmal die letzte Zeile ausgegeben werden.
>
>Wir man nun daraus das kryptische von oben macht:
>
># Deklaration und Initialisierung. Ohne use strict nicht erforderlich
># Der leere String ist Vorgabewert.
>my $last = "";
>
># Anstelle <STDIN> kann man auch <> schreiben als Kurzform
>while(my $line = <STDIN>)
>{
>
># Die Substition kann direkt in das if gezogen werden, da auch dort
># wahr zurück gegeben wird, wenn was ersetzt wurde
>  if ($line =~ /^\//)
>  {
>   $line =~ s/^\///;
>
># Das letzte Semikolon im Block darf fehlen
>   chomp $last;
>  }
>  print $last;
># Hier auch
>  $last = $line;
>}
># Und hier auch
>print $last;
>
>Damit hätten wir also folgendes:
>
>while(my $line = <>)
>{
>  if ($line =~ s/^\///)
>  {
>   chomp $last
>  }
>  print $last;
>  $last = $line
>}
>print $last
>
>Jetzt kommt eigentlich der Teil, der es erst richtig kryptisch werden
>lässt: Die Verwendung der Variablen $_
>
>Es gibt in Perl eine Reihe von immer definierten Variablen für
>verschiedene Zwecke, wobei $_ da mit die wichtigste ist. $_ ist synonym
>mit $ARG (was vielleicht schon etwas mehr über die Bedeutung verrät)
>und stellt den "standardmäßigen Eingabe- und Pattern-Matching-Raum"
>dar. Rein intuitiv enthält diese Variable immer genau das, was Perl
>meint, was man als Programmierer als nächstes braucht (naja, zumindest
>meistens). Wer es genau wissen will, wann die Variable was enhält, möge
>es bitte in entsprechender Perl-Literatur nachlesen; Mit der
>Beschreibung kann man fast eine Buchseite füllen. Ich gehe jetzt nur
>darauf ein, wo die Variable hier verwendet wird:
>
># Wir weisen die gelesene Eingabe keiner Variablen zu. Also landet sie
># in $_
>while(<>)
>{
># Jetzt verwenden wir $_
>  if ($_ =~ s/^\///)
>  {
>   chomp $last
>  }
>  print $last;
># Hier auch nochmal
>  $last = $_
>}
>print $last
>
>Wenn man nun noch die Variabel $last in $l umbenennt und alle
>Zeilenumbrüche entfernt, enthält man das obige.
>
>Im übrigen ist mir beim auseinandernehmen des Scripts aufgefallen, dass
>man noch viel mehr optimieren kann:
>
>while(<>)
>{
># Nur eine Zeile im if-Block kann man so umstellen
># Außerdem kann man beim Matching die Variable weglassen, dann wird
># implizit $_ verwendet
># Es sind auch andere Trenner beim Pattern-Matching zulässig, damit
># spart man sich das Escapen des /
>  chomp $last if (s!^/!!);
>  print $last;
>  $last = $_
>}
>print $last
>
>Was dann zu folgendem, wohl noch kryptischerem Ergebnis führt, vor
>allem, wenn man wirklich alle unnötigen Leerzeichen noch entfernt:
>
>perl -e'while(<>){chomp$l if(s!^/!!);print$l;$l=$_}print$l'
>
>Im übrigen habe ich noch eine alternative Version gebastelt, die noch
>kürzer ist, noch mehr implizite Dinge verwendet und demnach noch
>kryptischer ist. Allerdings hat diese Version die Macke, dass am Anfang
>ein Zeilenumbruch zu viel ausgegeben wird und am Ende einer fehlt:
>
>perl -pe'chomp;print"\n"unless s!^/!!'
>
>Und warum das ganze so ist und wie das Programm funktioniert, sei dem
>geneigten Leser als Übung überlassen. ;)
>
>Gruss
>
>Daniel

Also ich würde die Datei einfach in einen Editor 
laden und mit suchen/ersetzen die Zeilenumbrüche wieder korigieren.

Und ja das klappt sogar direkt in mehreren 
Dateien und nochmal ja der Editor ist freeware

Rolf






Mehr Informationen über die Mailingliste linux