Re: awk-Skript mit festem Arbeitsdateinamen

From: Polytropon <freebsd(at)edvax.de>
Date: Fri, 10 Apr 2009 18:05:56 +0200

On Fri, 10 Apr 2009 17:29:55 +0200 (CEST), Oliver Fromme <olli(at)lurza.secnetix.de> wrote:
> FILENAME ist read-only.

Das kam aus der Manpage nicht 100%ig heraus. Ich hatte
gehofft, daß FILENAME rw sei, so wie FS. :-(

> Du möchtest vermutlich ARGC und
> ARGV setzen.

Vermutlich. :-)

Das Handbuch sagt, diese wären rw.

> Mir ist allerdings unklar, warum Du den
> Namen der Eingabedatei im Script hardcoden möchtest.

Das ist pure Faulheit. Wenn das Skript +x ist, kann man
es einfach so starten, ohne Parameter dazugeben zu müssen.
Da sich die Eingabedatei ohnehin nicht ändert, wäre das
sehr bequem.

Bisher habe ich so an awk-Skripten ohne Eingabedatei
handeln können.

> (Alternativ kann man natürlich auch im BEGIN- oder END-
> Block »getline« in einer Schleife aufrufen.)

Das scheint machbar, dadurch wird $0 gesetzt und man kann
wieder auf die einzelnen Elemente zugreifen.

> > FILENAME = "blubb.csv";
> > FS = ":";
>
> Das sollte vermutlich in einem »BEGIN {...}« Block stehen.
> Alles, was außerhalb von Blöcken steht, wird als Pattern
> bzw. boolsche Ausdrücke interpretiert; obige Zuordnungen
> sind halt immer »True« und haben eine Default-Action.

Richtig, es führt dann sogar die Standardhandlung "print $0"
aus.

> Wenn awk ein kleines bisschen cleverer wäre, sollte er
> in solchen Fällen eine Warnung ausgeben.

Er, DER awk? Ich dachte immer, es wäre DAS awk. :-)

> Außerdem: Wenn es CSV-Dateien sind, dann solltest Du ","
> als Separator nehmen, nicht ":". Anderenfalls sind es
> keine CSV-Dateien.

Dann sind es CSV - colon separated values. :-) Aus dem Grund,
daß das , häufig in Feldern vorkommt, nehme ich recht gern den
: als Feldtrenner.

Bisher dachte ich, CSV wäre ein eher generischer Begriff für
eine Datei, deren Felder durch einen (beliebigen) Separator
getrennt seien. Daß CSV explizit das , verlangt, wußte ich
bisher nicht. Aber gut, wieder was gelernt zu haben.

> > !/^#/ && (length != 0) {
>
> /^[^#]/ ist kürzer und schneller. ;-)

Und das schmeißt auch die leeren Zeilen raus? Regex sind nicht
unbedingt meine Stärke, aber da steht doch jetzt "beginnt mit
Zeilenanfang, dann kein #", impliziert ^ an erster Stelle denn,
daß es eine nicht-leere Zeile sei?

> Also, Folgendes sollte funktionieren:
>
> #!/usr/bin/awk -f
>
> BEGIN {
> ARGV[1] = "blubb.csv"
> ARGC = 2
> FS = ","
> }
>
> /^[^#]/ {
> print $1, $2, $3
> ...
> }

Tut es! Perfekt.

> Nur so aus Spielerei: Man kann das gleiche auch in sh
> schreiben (einfacher und kürzer als in awk):
>
> #!/bin/sh -
>
> IFS=","
> while read line; do
> set -- $line
> echo $1 $2 $3
> ...
> done < blubb.csv

Ach, wenn's doch nur so wäre. :-) Das awk-Skript macht ein paar
sub()- bzw gsub()-Durchgänge, ein paar Konditionale und formuliert
dann mit printf() >> datei etwas in verschiedene Dateien.

Aber gut zu wissen, daß man in sh-Skripten nicht gleich umständlich
Konstrukte aus =`cut -f -d` oder | awk '{ print $x }' hernehmen
muß, wenn man mal auf separierte Dateien zugreifen will.

> Und das gleiche in Python würde wie folgt aussehen:
>
> #!/usr/bin/env python
>
> for line in file("blubb.csv"):
> if line and line[0] != "#":
> parts = line.split(",")
> print parts[0], parts[1], parts[2]
> ...

Mit split() habe ich in awk auch schon gute Erfahrungen machen
können, z. B.

        split("31 28 31 30 31 30 31 31 30 31 30 31", tage, " ");
        if(jahr % 4 == 0 && jahr % 100 != 0 || jahr % 400 == 0)
                tage[2]++;
        split("Januar Februar März April Mai Juni Juli August September \
                Oktober November Dezember", monatsname, " ");

Dann kann man mit dem Index schön drauf zugreifen und hat Monats-
namen und -länge.

Python sieht übrigens gar nicht uninteressant aus, ich denke,
das ist es wert, daß man sich damit mal näher befaßt.

Ein Perl-Verfechter würde nun natürlich sagen, daß das aktuell
diskutierte Thema exakt ein Fall für Perl sei. Und wahrscheinlich
würde das auch stimmen. :-)

Nur so als kurze Erklärung: Ich versuche gerade (d. h. dank der
Liste hier praktiziere ich bereits erfolgreich), ein aus einer
Datenbank (CSV) gespeistes System zur automatischen Erstellung
von Bewerbungsschreiben. Datei rein, Stapel aus Drucker raus.
Kurz, knapp, DIN und ISO, formal perfekt, immer derselbe Text,
nur ein paar spezielle Formen (z. B. Anrede und Titel) werden
beachtet. Der Zwischenschritt geht natürlich der Form halber
über LaTeX, also CSV -> awk -> LaTeX -> lpr -> Bewerbumm. :-)

Und selbst wenn das nicht sehr effizient ist, so übt es doch,
und es schärft das Auge dafür, wie man es besser machen könnte.
Das weiß man sowieso immer dann, wenn man mit etwas gerade fertig
geworden ist. :-)

-- 
Polytropon
>From Magdeburg, Germany
Happy FreeBSD user since 4.0
Andra moi ennepe, Mousa, ...
To Unsubscribe: send mail to majordomo(at)de.FreeBSD.org
with "unsubscribe de-bsd-questions" in the body of the message
Received on Fri 10 Apr 2009 - 18:06:10 CEST

search this site