Discussion:
Bestimmt Zeilen einer Datei addieren
(zu alt für eine Antwort)
Jens Kluesener
2005-10-20 19:31:27 UTC
Permalink
Hi

Ich habe eine Datei mit vielen Zeilen. In jeder Zeile sind irgendwelche
Einträge wie Wörter, Zahlen und ein Datum. Getrennt sind die Spalten
durch das #-Zeichen. Wie ich sie nach bestimmten Spalten sortiere weiß
ich. Ich möchte jetzt aber auch noch die Zeilen kombinieren wo die
Spalte 2 und Spalte 4 gleich sind. Dabei muß aber der Wert aus Spalte 3
addiert werden.

Also z.B.:

1 # AAA # 1,250 # 2005.05.02
1 # AAA # 2,250 # 2005.05.03
2 # BBB # 4,250 # 2005.05.02
2 # BBB # 8,250 # 2005.05.02
2 # AAA # 16,250 # 2005.05.03
3 # CCC # 32,250 # 2005.05.04
3 # CCC # 64,250 # 2005.05.04

Soll ergeben:

1 # AAA # 1,250 # 2005.05.02
1 # AAA # 2,250 # 2005.05.03
2 # BBB # 12,500 # 2005.05.02
2 # AAA # 16,250 # 2005.05.02
3 # CCC # 96,500 # 2005.05.02

Vielen Dank

Jens
Fabian Kurz
2005-10-20 21:34:50 UTC
Permalink
Post by Jens Kluesener
Ich habe eine Datei mit vielen Zeilen. In jeder Zeile sind irgendwelche
Einträge wie Wörter, Zahlen und ein Datum. Getrennt sind die Spalten
durch das #-Zeichen. Wie ich sie nach bestimmten Spalten sortiere weiß
ich. Ich möchte jetzt aber auch noch die Zeilen kombinieren wo die
Spalte 2 und Spalte 4 gleich sind. Dabei muß aber der Wert aus Spalte 3
addiert werden.
[...]

Schnell geschrieben und nur an deinem Beispiel getestet:

awk '{if (a==$3 && b==$7) {gsub(/,/,"",c); gsub(/,/,"",$5); \
sum=$5+c; if(sum<10000){fill=" "}else if(sum<100000){fill=" "}; \
sum = sprintf("%.3f", sum/1000); gsub(/\./,",",sum); print $1" \
"$2" "$3" "$4" "fill sum" "$6" "$7" "$8; printlast=0} else {if \
(printlast){print last}else{printlast=1}} a=$3; b=$7; c=$5; \
last=$0}' eingabedatei

HTH,
--
Fabian Kurz, DJ1YFK * Dresden, Germany * http://fkurz.net/
Bernd Nawothnig
2005-10-20 22:09:45 UTC
Permalink
Post by Fabian Kurz
Post by Jens Kluesener
Ich habe eine Datei mit vielen Zeilen. In jeder Zeile sind
irgendwelche Einträge wie Wörter, Zahlen und ein Datum. Getrennt sind
die Spalten durch das #-Zeichen. Wie ich sie nach bestimmten Spalten
^
Post by Fabian Kurz
Post by Jens Kluesener
sortiere weiß ich. Ich möchte jetzt aber auch noch die Zeilen
kombinieren wo die Spalte 2 und Spalte 4 gleich sind. Dabei muß aber
der Wert aus Spalte 3 addiert werden.
awk '{if (a==$3 && b==$7) {gsub(/,/,"",c); gsub(/,/,"",$5); \
^^^^^^^^^^^^^^^

Damit kannst Du nicht alle mehrfachen Vorkomnisse (auch über große
Distanzen) abdecken. Warum benutzt Du keine Arrays, die in awk genauso
Hashes wie in perl sind? Darüber einfach pro Hashwert aufsummieren und
fertig.
Post by Fabian Kurz
sum=$5+c; if(sum<10000){fill=" "}else if(sum<100000){fill=" "}; \
sum = sprintf("%.3f", sum/1000); gsub(/\./,",",sum); print $1" \
"$2" "$3" "$4" "fill sum" "$6" "$7" "$8; printlast=0} else {if \
^ ^ ^ ^ ^ ^

Die Leerzeichen, an denen awk defaultmäßig splittet (kann man das auch
ändern?) müssen laut Aufgabenstellung aber nicht vorhanden sein. Ich
hatte auch erst awk erwogen, aber Perls split an RegExps ist hier
entschieden mächtiger und darum einfacher in der Handhabung.




Bernd
--
Those who desire to give up freedom in order to gain security,
will not have, nor do they deserve, either one. [T. Jefferson]
Fabian Kurz
2005-10-20 22:22:08 UTC
Permalink
Post by Bernd Nawothnig
Post by Fabian Kurz
awk '{if (a==$3 && b==$7) {gsub(/,/,"",c); gsub(/,/,"",$5); \
^^^^^^^^^^^^^^^
Damit kannst Du nicht alle mehrfachen Vorkomnisse (auch über große
Distanzen) abdecken.
Das Beispiel sah fuer mich so aus, als seien die Daten soweit
sortiert, dass jene Zeilen nur nacheinander vorkommen koennen.
Post by Bernd Nawothnig
Warum benutzt Du keine Arrays, die in awk genauso Hashes wie in
perl sind? Darüber einfach pro Hashwert aufsummieren und
fertig.
Jo, waere sicher guenstiger gewesen.
Post by Bernd Nawothnig
Post by Fabian Kurz
sum=$5+c; if(sum<10000){fill=" "}else if(sum<100000){fill=" "}; \
sum = sprintf("%.3f", sum/1000); gsub(/\./,",",sum); print $1" \
"$2" "$3" "$4" "fill sum" "$6" "$7" "$8; printlast=0} else {if \
^ ^ ^ ^ ^ ^
Die Leerzeichen, an denen awk defaultmäßig splittet (kann man das auch
ändern?) müssen laut Aufgabenstellung aber nicht vorhanden sein.
Ja, ich weiss. Sollte aber schoen aussehen. (Jedenfalls die
Ausgabe :)
Post by Bernd Nawothnig
Ich hatte auch erst awk erwogen, aber Perls split an RegExps ist hier
entschieden mächtiger und darum einfacher in der Handhabung.
Wuerde wahrscheinlich auch eher Perl nehmen, aber dies war ein
Schnellschuss; und als ich mit awk angefangen hatte, wollte ich
es auch zuende bringen. Dein Ansatz gefaellt mir jedenfalls
deutlich besser als der meinige :-)
--
Fabian Kurz, DJ1YFK * Dresden, Germany * http://fkurz.net/
Bernd Nawothnig
2005-10-20 23:50:27 UTC
Permalink
Post by Fabian Kurz
Post by Bernd Nawothnig
Post by Fabian Kurz
sum=$5+c; if(sum<10000){fill=" "}else if(sum<100000){fill=" "}; \
sum = sprintf("%.3f", sum/1000); gsub(/\./,",",sum); print $1" \
"$2" "$3" "$4" "fill sum" "$6" "$7" "$8; printlast=0} else {if \
^ ^ ^ ^ ^ ^
Die Leerzeichen, an denen awk defaultmäßig splittet (kann man das auch
ändern?) müssen laut Aufgabenstellung aber nicht vorhanden sein.
Ja, ich weiss. Sollte aber schoen aussehen. (Jedenfalls die
Ausgabe :)
Nee, Dein Code würde im Fall, dass keine Leerzeichen vorhanden sind,
auch gar nicht funktionieren, weil ja die Zeile nicht in die
entsprechenden Felder gesplittet würde.

Was mich in diesem Zusammenhang interessierte - Du hattest darauf nicht
geantwortet - darum nochmals in die Runde gefragt: kann man das
Splitten der Zeilen durch awk auch an anderen Zeichen als an
Leerzeichen einstellen?
Post by Fabian Kurz
Post by Bernd Nawothnig
Ich hatte auch erst awk erwogen, aber Perls split an RegExps ist hier
entschieden mächtiger und darum einfacher in der Handhabung.
Wuerde wahrscheinlich auch eher Perl nehmen, aber dies war ein
Schnellschuss; und als ich mit awk angefangen hatte, wollte ich
es auch zuende bringen. Dein Ansatz gefaellt mir jedenfalls
deutlich besser als der meinige :-)
Mich würde interessieren, ob man es in awk ähnlich knapp und prägnant
hinbekommt. Wie gesagt, Hashes und die normalen
Programmiersprachenkonstrukte sind ja vorhanden.



Bernd
--
Those who desire to give up freedom in order to gain security,
will not have, nor do they deserve, either one. [T. Jefferson]
Stefan Lagotzki
2005-10-21 06:34:23 UTC
Permalink
Post by Bernd Nawothnig
Was mich in diesem Zusammenhang interessierte - Du hattest darauf nicht
geantwortet - darum nochmals in die Runde gefragt: kann man das
Splitten der Zeilen durch awk auch an anderen Zeichen als an
Leerzeichen einstellen?
Na klar. Indem man entweder mit -F ein anderes Trennzeichen
einstellt oder die Funktion split() einsetzt :-)

echo "A,B,C,D" | awk '{
split($0, a, ",");
printf("%s\n", a[3]);
}'

Und weil ich in awk assoziative Arrays habe, kann ich auch
so etwas hier machen:

echo "1 # AAA # 1,250 # 2005.05.02
1 # AAA # 2,250 # 2005.05.03
2 # BBB # 4,250 # 2005.05.02
2 # BBB # 8,250 # 2005.05.02
2 # AAA # 16,250 # 2005.05.03
3 # CCC # 32,250 # 2005.05.04
3 # CCC # 64,250 # 2005.05.04" |
awk -F '#' '{
a[sprintf("%s#%s#%s # ",$1, $2, $4)] += $3;
}
END {
for (F in a) {
printf("%s %7.3f %s\n", substr(F,1,9), a[F], substr(F,9,12))}
}' | sort -k 1


1 # AAA # 1,250 # 2005.05.02
1 # AAA # 2,250 # 2005.05.03
2 # AAA # 16,250 # 2005.05.03
2 # BBB # 12,500 # 2005.05.02
3 # CCC # 96,500 # 2005.05.04


Womit die Aufgabe in übersichtlichen sieben Zeilen awk auch
gelöst sein sollte :-)

Stefan

.
Stefan Lagotzki
2005-10-21 06:48:58 UTC
Permalink
Post by Stefan Lagotzki
Und weil ich in awk assoziative Arrays habe, kann ich auch
Wenn die Daten in einer Datei stehen, würde ich es so anwenden
(noch ein klein wenig bereinigt):

awk -F '#' '{
a[sprintf("%s#%s#%s",$1,$2,$4)] += $3;
}
END {
for (F in a) {
printf("%s %7.3f %s\n", substr(F,1,9), a[F], substr(F,9,12))}
}' daten.txt | sort -k 1


Der Schlüssel des Arrays sieht dann halt etwas ungewöhnlich aus:

***@platon:~/test> awk -F '#' '{
printf("%s#%s#%s\n",$1,$2,$4);
}' daten.txt

zum Beispiel so:

1 # AAA # 2005.05.02

Ich bin davon ausgegangen, dass die Felder 1 und 2 (1, AAA) jeweils
zusammengehören. Wenn nicht, müsste man das Skript ein wenig anpassen.

%% HTH, Stefan
Jens Klüsener
2005-10-21 08:51:29 UTC
Permalink
Wow, bin begeistert.

Um ehrlich zu sein verstehe ich davon nicht ein Wort. Aber das ist dann
wohl die Zeit sich damit auseinander zu setzen. Ich werde es mal Schritt
für Schritt zerflücken und sehen was passiert. Hat auch sein gutes. Aber
ganz ohne eure Hilfe würde ich gar nicht so weit kommen. Ich wüßte ja
gar nicht wie ich überhaupt vorgehen sollte.


Vielen Dank

Jens
Post by Stefan Lagotzki
Post by Stefan Lagotzki
Und weil ich in awk assoziative Arrays habe, kann ich auch
Wenn die Daten in einer Datei stehen, würde ich es so anwenden
awk -F '#' '{
a[sprintf("%s#%s#%s",$1,$2,$4)] += $3;
}
END {
for (F in a) {
printf("%s %7.3f %s\n", substr(F,1,9), a[F], substr(F,9,12))}
}' daten.txt | sort -k 1
printf("%s#%s#%s\n",$1,$2,$4);
}' daten.txt
1 # AAA # 2005.05.02
Ich bin davon ausgegangen, dass die Felder 1 und 2 (1, AAA) jeweils
zusammengehören. Wenn nicht, müsste man das Skript ein wenig anpassen.
%% HTH, Stefan
Stefan Lagotzki
2005-10-21 09:35:01 UTC
Permalink
Post by Jens Klüsener
Um ehrlich zu sein verstehe ich davon nicht ein Wort. Aber das ist dann
wohl die Zeit sich damit auseinander zu setzen. Ich werde es mal Schritt
für Schritt zerflücken und sehen was passiert. Hat auch sein gutes. Aber
ganz ohne eure Hilfe würde ich gar nicht so weit kommen. Ich wüßte ja
gar nicht wie ich überhaupt vorgehen sollte.
Für eine vernünftige Erklärung müsste man wissen, welche
Erfahrungen Du bisher gemacht hast. Wenn Du mit folgenden
Erklärungen nicht weiterkommst, schreib mir halt mal eine
PM (aber vor Samstagnachmittag wird es aus Arbeitsgründen
leider nichts).

Vorher noch eine Bemerkung: Was Du da beschrieben hast,
ist im Kern eigentlich ein Datenbankproblem. Datenbanken haben
gerade für solche zusammenfassenden Abfragen bereits sehr
zuverlässige Funktionen. Sollten die Daten also aus einer
Datenbank kommen oder sollte eine solche zur Verfügung stehen,
würde ich Dir die Anwendung einer Datenbank und einer SQL-
Abfrage empfehlen.

Ein paar Worte zu meinem Beispiel:

Man kann in den meisten Programmiersprachen eindimensionale
Arrays vereinbaren. Ein solches Array ist eine Aneinanderreihung
von Daten. Ein Element des Arrays muss immer einen Schlüssel
und einen Wert besitzen. Der Schlüssel kann einfach eine laufende
Nummer sein oder er kann eine bestimmte Beziehung zu dem Wert haben.

An einem Beispiel: Wenn ich die Umsätze einer Woche in ein Array
schreiben will, kann das zwei Formen haben. Ein numerisches Array
in der Form

Umsatz[1]=1000;
:
Umsatz[7]=1500;

oder ein assoziatives Array in der Form

Umsatz[Montag]=1000;
:
Umsatz[Sonntag]=1500;

Die assoziative Version verwende ich in meinem Beispiel. Du hast
gesagt, dass Du die Werte nach dem Feld 2 und dem Datum zusammen-
fassen willst. Ich bin davon ausgegangen, dass die Zahl in der
ersten Spalte auch mit dazugehört. Ich baue mir also auch ein
solches Array auf, in dem ich die Felder 1, 2 und 4 als Schlüssel
verwende. Nun wird der Wert in diesem Array für einen bestimmten
Schlüssel jeweils aufaddiert und am Ende der Verarbeitung aller
Dateizeilen wird das Array ausgewertet. Da ich keinen Einfluss auf
die Sortierung habe und da ich mir eine Sortierfunktion in awk
ersparen wollte, verwende ich 'sort' zum Sortieren der Ausgabe.

HTH && HAND,
Stefan

.
Jens Klüsener
2005-10-21 13:24:04 UTC
Permalink
Post by Stefan Lagotzki
Post by Jens Klüsener
Um ehrlich zu sein verstehe ich davon nicht ein Wort. Aber das ist
dann wohl die Zeit sich damit auseinander zu setzen. Ich werde es mal
Schritt für Schritt zerflücken und sehen was passiert. Hat auch sein
gutes. Aber ganz ohne eure Hilfe würde ich gar nicht so weit kommen.
Ich wüßte ja gar nicht wie ich überhaupt vorgehen sollte.
Für eine vernünftige Erklärung müsste man wissen, welche
Erfahrungen Du bisher gemacht hast. Wenn Du mit folgenden
Erklärungen nicht weiterkommst, schreib mir halt mal eine
PM (aber vor Samstagnachmittag wird es aus Arbeitsgründen
leider nichts).
Nee, ich sag ja. Damit muß ich mich einfach mal beschäftigen. Da werde
ich wohl auch in Zukunft nicht drum rum kommen.
Post by Stefan Lagotzki
Vorher noch eine Bemerkung: Was Du da beschrieben hast,
ist im Kern eigentlich ein Datenbankproblem. Datenbanken haben
gerade für solche zusammenfassenden Abfragen bereits sehr
zuverlässige Funktionen. Sollten die Daten also aus einer
Datenbank kommen oder sollte eine solche zur Verfügung stehen,
würde ich Dir die Anwendung einer Datenbank und einer SQL-
Abfrage empfehlen.
Klar, in SQL wäre das ein Kinderspiel. Ich habe es aber leider nur in
einer Textdatei und kann das auch nicht ändern. Leider.

Ciao jens
Bernd Nawothnig
2005-10-21 16:19:38 UTC
Permalink
Post by Jens Klüsener
Post by Jens Klüsener
Um ehrlich zu sein verstehe ich davon nicht ein Wort. Aber das ist
dann wohl die Zeit sich damit auseinander zu setzen. Ich werde es
mal Schritt für Schritt zerflücken und sehen was passiert. Hat auch
sein gutes. Aber ganz ohne eure Hilfe würde ich gar nicht so weit
kommen. Ich wüßte ja gar nicht wie ich überhaupt vorgehen sollte.
Für eine vernünftige Erklärung müsste man wissen, welche Erfahrungen
Du bisher gemacht hast. Wenn Du mit folgenden Erklärungen nicht
weiterkommst, schreib mir halt mal eine PM (aber vor
Samstagnachmittag wird es aus Arbeitsgründen leider nichts).
Nee, ich sag ja. Damit muß ich mich einfach mal beschäftigen. Da werde
ich wohl auch in Zukunft nicht drum rum kommen.
[...]
Post by Jens Klüsener
Klar, in SQL wäre das ein Kinderspiel. Ich habe es aber leider nur in
einer Textdatei und kann das auch nicht ändern. Leider.
Auch Perl, Python oder Ruby kommen für solche und ähnliche Probleme
immer in Betracht, speziell, wenn man etwas mehr damit vor hat. Hashes
(AKA assoziative Arrays) und reguläre Ausdrücke kennen sie alle drei,
darüber hinaus z.B. noch Listen. Und schnell entwickeln (keine
Compilerläufe, intuitive Benutzung) kann man auch mit allen dreien.
Dokumentation und Tutorials gibt's wie Sand am Meer (für Ruby noch
nicht so üppig, aber immer noch ausreichend). Python ist mehr in
Richtung echte, objektorientierte Programmiersprache von Anfang an
angelegt und damit auch für größere Aufgaben, Perl will C-Shell, sed
und awk vereinen (man findet vieles dort wieder), kennt aber inzwischen
auch Objektorientierung und Ruby ist konsequent objektorientiert
angelegt (konsequenter als Python oder Perl).

Unter dem Aspekt späterer Wartbar- bzw. Erweiterbarkeit würde ich Dir
empfehlen, Dir mal Ruby oder Python näher anzuschauen.



Bernd
--
Those who desire to give up freedom in order to gain security,
will not have, nor do they deserve, either one. [T. Jefferson]
Bernd Nawothnig
2005-10-21 08:42:02 UTC
Permalink
Post by Stefan Lagotzki
Und weil ich in awk assoziative Arrays habe, kann ich auch so etwas
Erstmal vielen Dank für Deine Anmerkungen. Ich lerne nämlich gerade
awk und danach sieht das nun doch recht gut benutzbar aus ...
Post by Stefan Lagotzki
Wenn die Daten in einer Datei stehen, würde ich es so anwenden
awk -F '#' '{
a[sprintf("%s#%s#%s",$1,$2,$4)] += $3;
}
END {
for (F in a) {
printf("%s %7.3f %s\n", substr(F,1,9), a[F], substr(F,9,12))}
}' daten.txt | sort -k 1
... und braucht sich keineswegs hinter perl zu verstecken.
Post by Stefan Lagotzki
printf("%s#%s#%s\n",$1,$2,$4);
}' daten.txt
1 # AAA # 2005.05.02
Hatte ich ähnlich gemacht, nur die Felder 2 und 4 zusammengepackt und
das erste separat gespeichert, was allerdings wohl nicht ganz korrekt
war, wie mir im nachhinein auffällt. Allerdings hast Du die Blanks
stehen gelassen. Die hatte ich in meiner Perllösung vorher entfernt,
weil sie mir nicht als signifikant erschienen.



Bernd
--
Those who desire to give up freedom in order to gain security,
will not have, nor do they deserve, either one. [T. Jefferson]
Stefan Lagotzki
2005-10-21 09:42:45 UTC
Permalink
Post by Bernd Nawothnig
Erstmal vielen Dank für Deine Anmerkungen. Ich lerne nämlich gerade
awk und danach sieht das nun doch recht gut benutzbar aus ...
Viel Freude damit :-) Es gibt ja eine Menge Wissensquellen zu
awk im Web. Perl ist natürlich eine sehr vitale Sprache und es
entwickelt sich schnell weiter. Auch die Menge der vorhandenen
Module ist viel größer als bei awk.
Post by Bernd Nawothnig
Hatte ich ähnlich gemacht, nur die Felder 2 und 4 zusammengepackt und
das erste separat gespeichert, was allerdings wohl nicht ganz korrekt
war, wie mir im nachhinein auffällt. Allerdings hast Du die Blanks
stehen gelassen. Die hatte ich in meiner Perllösung vorher entfernt,
weil sie mir nicht als signifikant erschienen.
Was das Feld 1 betrifft: Mir scheint es so, als ob das Feld
redundant ist -- zumindest nach den bekannten Daten.
Der Fragesteller müsste sich dazu vielleicht noch mal genauer
äußern. Wie ich schon in dem anderen Posting sagte, sehe ich
das eher als ein Datenbankproblem. Man kann es aber mit Perl
und awk auch ziemlich gut lösen.

Die Blanks brauchte ich ja noch, weil ich sie gleich in die
Formatierung der Ausgabe übernehmen wollte. Sie stören ja auch
nicht weiter.

Stefan

.
Bernd Nawothnig
2005-10-21 10:51:30 UTC
Permalink
Post by Stefan Lagotzki
Post by Bernd Nawothnig
Erstmal vielen Dank für Deine Anmerkungen. Ich lerne nämlich gerade
awk und danach sieht das nun doch recht gut benutzbar aus ...
Viel Freude damit :-) Es gibt ja eine Menge Wissensquellen zu
awk im Web. Perl ist natürlich eine sehr vitale Sprache und es
entwickelt sich schnell weiter. Auch die Menge der vorhandenen
Module ist viel größer als bei awk.
Das natürlich. Aber erstens präferiere ich für komplexere Sachen eher
Python und zweitens wollte ich diesen weißen Flecken awk in meiner
Landkarte endlich mal austilgen :-). Und besser lesbar als perl ist awk
definitiv.
Post by Stefan Lagotzki
Post by Bernd Nawothnig
Hatte ich ähnlich gemacht, nur die Felder 2 und 4 zusammengepackt und
das erste separat gespeichert, was allerdings wohl nicht ganz korrekt
war, wie mir im nachhinein auffällt. Allerdings hast Du die Blanks
stehen gelassen. Die hatte ich in meiner Perllösung vorher entfernt,
weil sie mir nicht als signifikant erschienen.
Was das Feld 1 betrifft: Mir scheint es so, als ob das Feld
redundant ist -- zumindest nach den bekannten Daten.
Der Fragesteller müsste sich dazu vielleicht noch mal genauer
äußern. Wie ich schon in dem anderen Posting sagte, sehe ich
das eher als ein Datenbankproblem. Man kann es aber mit Perl
und awk auch ziemlich gut lösen.
Die Blanks brauchte ich ja noch, weil ich sie gleich in die
Formatierung der Ausgabe übernehmen wollte. Sie stören ja auch
nicht weiter.
Sie stören, wenn sie nicht signifikant sind, aber in unterschiedlicher
Anzahl vorkommen können. In dem Fall legt awk nämlich z.B. für

# xyz # ...

#xyz# ...

zwei unterschiedliche Elemente im Array an, was aber falsch wäre, wenn
sie als gleich gelten sollen. Deswegen mein absichtliches

#v+
split / *# */;
#v-

statt

#v+
split /#/;
#v-

(was ebenso möglich gewesen wäre)




Bernd
--
Those who desire to give up freedom in order to gain security,
will not have, nor do they deserve, either one. [T. Jefferson]
David Haller
2005-10-22 00:33:33 UTC
Permalink
Und besser lesbar als perl ist awk definitiv.
Einspruch. Perl kann man sehr wohl lesbar schreiben. IMO oft sogar
lesbarer als bash, awk, sed, PHP, C, C++ u.a. Es gibt aber sicherlich
viel Code der unleserlich ist, aber as liegt nicht an perl selbst
sondern an den Programmierern.

Apropos: perl -MO=Deparse -e '...' kann beim leserlich machen helfen.

Ich finde z.B. viele Idiome, die ich nur von perl kenne sehr intuitiv,
allein das "do_something or die "Argh!\n" ist IMHO genial, Motto: "friss
oder stirb!" :) In anderen Sprachen ist sowas immer ein langweiliges:
if( ! do_something ) { die "Argh!\n"; }
oder Variationen davon. Ok, die Bash / POSIX-shell kennt auch sowas:
command || { echo "Argh!" >&2; exit 1; }
was aber schon weniger gut lesbar ist.

[..]
zwei unterschiedliche Elemente im Array an, was aber falsch wäre, wenn
sie als gleich gelten sollen. Deswegen mein absichtliches
split / *# */;
statt
split /#/;
awk -F '/ *# */' '...'

BTW:
==== perldoc perlvar ====
Remember: the value of $/ is a string, not a
regex. awk has to be better for something. :-)
====

Jedenfalls: awk kann sehr wohl an einer RE "split"en. Sowohl Zeilen
als auch Felder.

-dnh

PS: ich mag bash, sed, awk!
--
Ah, the curse of having old files lying around collecting dust. That
file has been sitting on the system for about a decade. Never caused
any trouble before now, probably because the teTeX supplied file won
out in the kpathsea lottery. -- Harald Hanche-Olsen on the tetex-ML
Bernd Nawothnig
2005-10-22 08:21:37 UTC
Permalink
Post by David Haller
Und besser lesbar als perl ist awk definitiv.
Einspruch. Perl kann man sehr wohl lesbar schreiben.
auf den Einspruch habe ich schon sehnsüchtig gewartet ;-)
Post by David Haller
IMO oft sogar lesbarer als bash, awk, sed, PHP, C, C++ u.a. Es gibt
aber sicherlich viel Code der unleserlich ist, aber as liegt nicht an
perl selbst sondern an den Programmierern.
Naja. So ganz stimmt das nicht, Perl legt einen gewissen
Programmierstil schon recht nahe.
Post by David Haller
Apropos: perl -MO=Deparse -e '...' kann beim leserlich machen helfen.
Ich finde z.B. viele Idiome, die ich nur von perl kenne sehr intuitiv,
Ja. Perl ist eindeutig intuitiv und ich wunderte mich selber, wie
schnell ich nach gewiss 2 Jahren Perl-Abstinenz das Problem des OPs in
Perl lösen konnte.
Post by David Haller
allein das "do_something or die "Argh!\n" ist IMHO genial, Motto: "friss
oder stirb!" :)
ACK
Post by David Haller
In anderen Sprachen ist sowas immer ein langweiliges: if( !
do_something ) { die "Argh!\n"; } oder Variationen davon. Ok, die Bash
/ POSIX-shell kennt auch sowas: command || { echo "Argh!" >&2; exit 1;
} was aber schon weniger gut lesbar ist.
Da mag ich solche Konstrukte auch nicht.
Post by David Haller
[..]
zwei unterschiedliche Elemente im Array an, was aber falsch wäre, wenn
sie als gleich gelten sollen. Deswegen mein absichtliches
split / *# */;
statt
split /#/;
awk -F '/ *# */' '...'
Genau das fehlte mir für die saubere awk-Lösung - Danke!



Bernd
--
Those who desire to give up freedom in order to gain security,
will not have, nor do they deserve, either one. [T. Jefferson]
Jens Klüsener
2005-10-21 13:25:42 UTC
Permalink
Post by Stefan Lagotzki
Viel Freude damit :-) Es gibt ja eine Menge Wissensquellen zu
awk im Web.
Hm, ich habe da vorhin mal nach gesucht. Was wirklich umfassendes habe
ich da nicht auf die Schnelle gefunden. Hast du da einen Tip im Web für
mich?

Vielen Dank
J. Seyfferth
2005-10-21 20:58:20 UTC
Permalink
Hallo,
Post by Jens Klüsener
Es gibt ja eine Menge Wissensquellen zu awk im Web.
Hm, ich habe da vorhin mal nach gesucht. Was wirklich umfassendes habe
ich da nicht auf die Schnelle gefunden. Hast du da einen Tip im Web für
mich?
Vielleicht hilft Dir das weiter:

The GNU Awk User's Guide
http://www.gnu.org/software/gawk/manual/
--
Mit freundlichen Gruessen
J. Seyfferth

Bill, Gates noch?
Bernd Nawothnig
2005-10-20 21:42:16 UTC
Permalink
Post by Jens Kluesener
Ich habe eine Datei mit vielen Zeilen. In jeder Zeile sind
irgendwelche Einträge wie Wörter, Zahlen und ein Datum. Getrennt sind
die Spalten durch das #-Zeichen. Wie ich sie nach bestimmten Spalten
sortiere weiß ich. Ich möchte jetzt aber auch noch die Zeilen
kombinieren wo die Spalte 2 und Spalte 4 gleich sind. Dabei muß aber
der Wert aus Spalte 3 addiert werden.
1 # AAA # 1,250 # 2005.05.02
1 # AAA # 2,250 # 2005.05.03
2 # BBB # 4,250 # 2005.05.02
2 # BBB # 8,250 # 2005.05.02
2 # AAA # 16,250 # 2005.05.03
3 # CCC # 32,250 # 2005.05.04
3 # CCC # 64,250 # 2005.05.04
1 # AAA # 1,250 # 2005.05.02
1 # AAA # 2,250 # 2005.05.03
2 # BBB # 12,500 # 2005.05.02
2 # AAA # 16,250 # 2005.05.02
3 # CCC # 96,500 # 2005.05.02
Nicht ganz On Topic, aber ich muss meine eingerosteten Perl-Kenntnisse
mal wieder etwas auffrischen:

#v+
#!/usr/bin/perl

foreach (<STDIN>) {
chomp;
@l = split / *# */;
$i = $l[1]."#".$l[3];
$_ = $l[2];
s/,/\./;
$t1{$i} = $l[0];
$t2{$i} += $_;
}

foreach (sort keys %t2) {
@k1 = split /#/;
print "$t1{$key} # $k1[0] # $t2{$_} # $k1[1]\n";
}
#v-




Bernd
--
Those who desire to give up freedom in order to gain security,
will not have, nor do they deserve, either one. [T. Jefferson]
Bernd Nawothnig
2005-10-20 21:51:53 UTC
Permalink
Post by Bernd Nawothnig
print "$t1{$key} # $k1[0] # $t2{$_} # $k1[1]\n";
print "$t1{$_} # $k1[0] # $t2{$_} # $k1[1]\n";

Sorry, hatte nicht alles auf den letzten Stand gebracht.



Bernd
--
Those who desire to give up freedom in order to gain security,
will not have, nor do they deserve, either one. [T. Jefferson]
Lesen Sie weiter auf narkive:
Suchergebnisse für 'Bestimmt Zeilen einer Datei addieren' (Fragen und Antworten)
6
Antworten
Ich habe eine Excel-Tabelle abgespeichert...?
gestartet 2011-03-18 11:45:17 UTC
programmierung & design
Loading...