Tabellenproblem, awk oder perl?
Moin, ich habe folgendes Problem: Ich habe 2 Dateien die jeweils eine 2-reihige Tabelle enthalten, wobei die jeweils erste Reihe in beiden Tabellen gleich ist (forlaufender Index, 4095 Zeilen) und ich will diese zunächst nun in eine 3-reihige Tabelle überführen. Später muss durch einen mathematischen Formalismus aus den drei Reihen auch noch eine 4. Reihe generiert werden. Da die beiden Ausgangs-Dateien als Standart-output aus einem Messystem kommen, auf die stets der selbe Auswertungsalgorithmus angewendet werden soll brauche ich ein script, dass diese Dateien autmoatisiert verarbeiten kann und eine standartisierte Ausgangsdatei mit 4 Reihen erzeugt. Im Ergebnis sollte dann sowas wie 1. 2. 3. 4. Index Daten1 Daten2 Funktion(Index,Daten1,Daten2) herauskommen. Ich wollte es mit gawk realisieren. Allerdings ist mir nicht klar, wie man mit gawk Dateien zusammenführt. So habe ich die beiden Dateien erstmal sequentiell aneinandergehängt und wollte dann durch Verschieben des gwak-Parameters FNR die $2 von FNR+4095 auslesen, was aber so nicht hinhaut. Vielleicht sollte man es besser gleich mit perl veruchen, aber damit kenne ich mich leider gar nicht aus. Hat jemand eine Idee oder kann mir im groben aufzeigen, wie man da dran geht? Gruß, Hannes
Moin,
ich habe folgendes Problem:
Ich habe 2 Dateien die jeweils eine 2-reihige Tabelle enthalten, wobei die jeweils erste Reihe in beiden Tabellen gleich ist (forlaufender Index, 4095 Zeilen) und ich will diese zunächst nun in eine 3-reihige Tabelle überführen. Später muss durch einen mathematischen Formalismus aus den drei Reihen auch noch eine 4. Reihe generiert werden. Da die beiden Ausgangs-Dateien als Standart-output aus einem Messystem kommen, auf die stets der selbe Auswertungsalgorithmus angewendet werden soll brauche ich ein script, dass diese Dateien autmoatisiert verarbeiten kann und eine standartisierte Ausgangsdatei mit 4 Reihen erzeugt. Im Ergebnis sollte dann sowas wie
1. 2. 3. 4. Index Daten1 Daten2 Funktion(Index,Daten1,Daten2)
herauskommen.
Ich wollte es mit gawk realisieren. Allerdings ist mir nicht klar, wie man mit gawk Dateien zusammenführt. So habe ich die beiden Dateien erstmal sequentiell aneinandergehängt und wollte dann durch Verschieben des gwak-Parameters FNR die $2 von FNR+4095 auslesen, was aber so nicht hinhaut.
Das ist glaube ich zu viel Amok gawk dazu zu bringen mit 2 Eingabedateien zu arbeiten.
Vielleicht sollte man es besser gleich mit perl veruchen, aber damit kenne ich mich leider gar nicht aus.
mit perl ist das ein Kinderspiel. Das sind wahrscheinlich nur einige wenige Zeilen. Bin leider etwas eingerostet. Könnte aber mal ein beispiel schreiben. Allerdings nicht mehr heute. Währe vielleicht gnuplot eine Alternative wenn die Daten nachher sowieso grafisch dargestellt werden müssen? Das könnte dann die Daten gleich grafisch darstellen.
Hat jemand eine Idee oder kann mir im groben aufzeigen, wie man da dran geht?
Gruß, Hannes
-- Um die Liste abzubestellen, schicken Sie eine Mail an: suse-linux-unsubscribe@suse.com Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: suse-linux-help@suse.com
-- Falko Zurell Consultant Avinci AG
Hallo, Am Wed, 23 Jun 2004, Falko Zurell schrieb:
Das ist glaube ich zu viel Amok gawk dazu zu bringen mit 2 Eingabedateien zu arbeiten.
Awatt. gawk -F"sep" '{ getline line < "file2"; split(line, array, "sep"); printf "%08i %s %s %s\n", $1, $2, array[2], $2 * array[2]; }' < "file1" Oder aehnliches. -dnh -- I swear that this abortion combines the worst screwups in NT, Win2K & Windows 98, all rolled into one, then splashed with one of the most nauseating GUIs[2] it's even been my misfortune to be required not to puke on. -- Lionel on "Windows XP"
hi!
diese zunächst nun in eine 3-reihige Tabelle überführen. Später muss durch einen mathematischen Formalismus aus den drei Reihen auch noch eine 4. Reihe generiert werden. Da die beiden Ausgangs-Dateien als Standart-output aus einem Messystem kommen, auf die stets der selbe Auswertungsalgorithmus angewendet werden soll brauche ich ein script, dass diese Dateien autmoatisiert verarbeiten kann und eine standartisierte Ausgangsdatei mit 4 Reihen erzeugt. Im Ergebnis sollte dann sowas wie
hi hannes! ungef. lösungsansatz in perl: #!/usr/bin/perl # untested $f1 = "/erste/datei"; $f2 = "/zweite/datei"; $sep = "separator"; # IFS $fout = "/merged/datei"; open( F1, "< $f1") or die "cant open $f1: $!"; while (<F1>) # zeilen einlesen nach $_ { chomp($_); # auseinanderschneiden am sep. und erstes # feld als key ($key, @rest) = split(/$sep/, $_); # wieder zusammenführen und unter $key ablegen # hash = assoz.array $hash{$key} = join($sep, @rest); } close F1; open( F2, "< $f2") or die "cant open $f2: $!"; while (<F2>) # zeilen einlesen nach $_ { chomp($_); # auseinanderschneiden am sep. und erstes # feld als key ($key, @rest) = split(/$sep/, $_); # wieder zusammenführen und unter $key ablegen # diesmal aber die ersten spalten dazu $hash{$key} = join($sep, $hash{$key}, @rest); } close F2; open(FOUT, "> $fout") or die "cant write $fout: $!"; foreach (sort keys %hash) { print FOUT join($sep, $_, $hash{$_}), "\n"; } close FOUT; print "Fertig";
Hi, Am Mit, 23 Jun 2004, schrieb Dominik Schopper:
ungef. lösungsansatz in perl:
[...] Hmmm, macht teilweise schon das richtige, allerdings bringt es die Zeilen total durcheinander, weil es die Zeilen nach den Inhalten des jeweils ersten Feldes sortiert. Das sieht dann z.B. so aus: 0 646543 0 0 646638 0 1 636858 0 1 639937 0 10 643148 0 10 648916 0 100 641890 0 100 647527 0 1000 720644 0 1000 877545 0 1001 718964 0 1001 895110 0 1002 713754 0 1002 877844 0 1003 718324 0 1003 886145 0 1004 714798 0 1004 884013 0 1005 711439 0 1005 873382 0 1006 717328 0 1006 887898 0 1007 716662 0 1007 874269 0 1008 711683 0 1008 881582 0 1009 727464 0 1009 883066 0 101 638048 0 Die Zeilen müssen aber in der richtigen Reihenfolge bleiben, da der Zeilenindex auch eine physikalische Bedeutung in Bezug auf die beiden anderen Spalten hat. Mir ist aber schon nicht klar wo die Neusortierung stattfindet, beim Einlesen oder beim Zusammenfügen. Aber Danke schonmal für die Bemühungen. Ich muss mich wohl dochmal näher mit perl beschäftigen. Gruß, Hannes
Hallo, On Wednesday 23 June 2004 18:06, Hannes Vogelmann wrote:
Hi,
Am Mit, 23 Jun 2004, schrieb Dominik Schopper:
ungef. lösungsansatz in perl:
[...]
Hmmm, macht teilweise schon das richtige, allerdings bringt es die Zeilen total durcheinander, weil es die Zeilen nach den Inhalten des jeweils ersten Feldes sortiert. Das sieht dann z.B. so aus:
0 646543 0 0 646638 0 1 636858 0 1 639937 0 10 643148 0 10 648916 0 100 641890 0 100 647527 0 1000 720644 0 1000 877545 0 1001 718964 0 1001 895110 0 1002 713754 0 1002 877844 0 1003 718324 0 1003 886145 0 1004 714798 0 1004 884013 0 1005 711439 0 1005 873382 0 1006 717328 0 1006 887898 0 1007 716662 0 1007 874269 0 1008 711683 0 1008 881582 0 1009 727464 0 1009 883066 0 101 638048 0
Die Zeilen müssen aber in der richtigen Reihenfolge bleiben, da der Zeilenindex auch eine physikalische Bedeutung in Bezug auf die beiden anderen Spalten hat. Mir ist aber schon nicht klar wo die Neusortierung stattfindet, beim Einlesen oder beim Zusammenfügen. Aber Danke schonmal für die Bemühungen. Ich muss mich wohl dochmal näher mit perl beschäftigen.
Die Neusortierung findet hier statt: foreach (sort keys %hash) # ^^^^ { print FOUT join($sep, $_, $hash{$_}), "\n"; } Allerdings sortiert Perl in den Hashs auch schon vor. Entweder schreibt man sich also eine eigene Sortierfunktion, die sort übergeben wird, oder man nimmt eine andere Variante, die am besten nicht gleich die Daten in einen Hash einliest. Bei großen Dateien könnte das Probleme machen. Ferdinand
On Wednesday 23 June 2004 18:51, Ferdinand Ihringer wrote:
Hallo,
On Wednesday 23 June 2004 18:06, Hannes Vogelmann wrote:
Hi,
Am Mit, 23 Jun 2004, schrieb Dominik Schopper:
ungef. lösungsansatz in perl:
[...]
Hmmm, macht teilweise schon das richtige, allerdings bringt es die Zeilen total durcheinander, weil es die Zeilen nach den Inhalten des jeweils ersten Feldes sortiert. Das sieht dann z.B. so aus:
0 646543 0 0 646638 0 1 636858 0 1 639937 0 10 643148 0 10 648916 0 100 641890 0 100 647527 0 1000 720644 0 1000 877545 0 1001 718964 0 1001 895110 0 1002 713754 0 1002 877844 0 1003 718324 0 1003 886145 0 1004 714798 0 1004 884013 0 1005 711439 0 1005 873382 0 1006 717328 0 1006 887898 0 1007 716662 0 1007 874269 0 1008 711683 0 1008 881582 0 1009 727464 0 1009 883066 0 101 638048 0
Die Zeilen müssen aber in der richtigen Reihenfolge bleiben, da der Zeilenindex auch eine physikalische Bedeutung in Bezug auf die beiden anderen Spalten hat. Mir ist aber schon nicht klar wo die Neusortierung stattfindet, beim Einlesen oder beim Zusammenfügen. Aber Danke schonmal für die Bemühungen. Ich muss mich wohl dochmal näher mit perl beschäftigen.
Die Neusortierung findet hier statt: foreach (sort keys %hash) # ^^^^ { print FOUT join($sep, $_, $hash{$_}), "\n"; }
Allerdings sortiert Perl in den Hashs auch schon vor. Entweder schreibt man sich also eine eigene Sortierfunktion, die sort übergeben wird, oder man nimmt eine andere Variante, die am besten nicht gleich die Daten in einen Hash einliest. Bei großen Dateien könnte das Probleme machen.
Also so abgewandelt, wenn ich alles richtig verstanden: #!/usr/bin/perl use strict; use warnings; # Dieses Skript geht davon aus, dass beide Dateien die selbe Zeilenlaenge # haben # Ausnahmen wie leere Zeilen ueberspringen koennte man noch einbauen. Außerdem # sollten die Daten in der selben Reihenfolge stehen. Das trifft, wenn ich alles # richtig verstand,, alles zu. # auch untested my $f1 = "/erste/datei"; my $f2 = "/zweite/datei"; my $sep = "separator"; # IFS my $fout = "/merged/datei"; open( F1, "< $f1") or die "cant open $f1: $!"; open( F2, "< $f2") or die "cant open $f2: $!"; open(FOUT, "> $fout") or die "cant write $fout: $!"; while (!(eof(F1) or eof(F2))) { #Zeilen einlesen und Umbrueche #entfernen my $f1l = <F1>; my $f2l = <F2>; chomp($f1l); chomp($f2l); # auseinanderschneiden am sep. my ($index1, $index2, @dat1, @dat2); ($index1,@dat1) = split(/$sep/, $f1l); ($index2,@dat2) = split(/$sep/, $f2l); #Die Indecie sollten gleich sein die "Das Script muss noch verbessert werden.\n" if $index1 != $index2; #Hier könnte man die Rechenoperation fuer die vierte Spalte durchfuehren #Alles in die neue Datei schreiben print FOUT join($sep, $index1, @dat1, @dat2),"\n"; } close F1; close F2; close FOUT; print "Fertig\n"; Wenn wirklich beide Dateien gleich viele Zeilen und in der selben Anordnung indiziert sind, geht das so und es wäre wesentlich speicherschonender. Ferdinand
Hannes Vogelmann schrieb:
Moin,
ich habe folgendes Problem:
Ich habe 2 Dateien die jeweils eine 2-reihige Tabelle enthalten, wobei die jeweils erste Reihe in beiden Tabellen gleich ist (forlaufender Index, 4095 Zeilen) und ich will diese zunächst nun in eine 3-reihige Tabelle überführen. Später muss durch einen mathematischen Formalismus aus den drei Reihen auch noch eine 4. Reihe generiert werden. Da die beiden Ausgangs-Dateien als Standart-output aus einem Messystem kommen, auf die stets der selbe Auswertungsalgorithmus angewendet werden soll brauche ich ein script, dass diese Dateien autmoatisiert verarbeiten kann und eine standartisierte Ausgangsdatei mit 4 Reihen erzeugt. Im Ergebnis sollte dann sowas wie
1. 2. 3. 4. Index Daten1 Daten2 Funktion(Index,Daten1,Daten2)
herauskommen.
Ich wollte es mit gawk realisieren. Allerdings ist mir nicht klar, wie man mit gawk Dateien zusammenführt. So habe ich die beiden Dateien erstmal sequentiell aneinandergehängt und wollte dann durch Verschieben des gwak-Parameters FNR die $2 von FNR+4095 auslesen, was aber so nicht hinhaut.
Vielleicht sollte man es besser gleich mit perl veruchen, aber damit kenne ich mich leider gar nicht aus.
Hat jemand eine Idee oder kann mir im groben aufzeigen, wie man da dran geht?
man join ;) join file1 file2 | awk '{erg=$2*$3;printf("%-40s : %20.10f",$0,erg);}' Gruss bernd
Am Mit, 23 Jun 2004, schrieb Bernd Obermayr:
Hannes Vogelmann schrieb:
Moin,
ich habe folgendes Problem:
Ich habe 2 Dateien die jeweils eine 2-reihige Tabelle enthalten, wobei die jeweils erste Reihe in beiden Tabellen gleich ist (forlaufender Index, 4095 Zeilen) und ich will diese zunächst nun in eine 3-reihige Tabelle überführen. Später muss durch einen mathematischen Formalismus aus den drei Reihen auch noch eine 4. Reihe generiert werden. Da die beiden Ausgangs-Dateien als Standart-output aus einem Messystem kommen, auf die stets der selbe Auswertungsalgorithmus angewendet werden soll brauche ich ein script, dass diese Dateien autmoatisiert verarbeiten kann und eine standartisierte Ausgangsdatei mit 4 Reihen erzeugt. Im Ergebnis sollte dann sowas wie
1. 2. 3. 4. Index Daten1 Daten2 Funktion(Index,Daten1,Daten2)
herauskommen.
Ich wollte es mit gawk realisieren. Allerdings ist mir nicht klar, wie man mit gawk Dateien zusammenführt. So habe ich die beiden Dateien erstmal sequentiell aneinandergehängt und wollte dann durch Verschieben des gwak-Parameters FNR die $2 von FNR+4095 auslesen, was aber so nicht hinhaut.
Vielleicht sollte man es besser gleich mit perl veruchen, aber damit kenne ich mich leider gar nicht aus.
Hat jemand eine Idee oder kann mir im groben aufzeigen, wie man da dran geht?
man join ;)
join file1 file2 | awk '{erg=$2*$3;printf("%-40s : %20.10f",$0,erg);}'
verblüffend einfach, aber macht genau das, was ich will ;-)) Da muss man auch erstmal draufkommen. Von joint hatte ich nie was gehört. Den awk-Teil hatte ich schon so in etwa, nur nicht die Daten im richtigen Format. Vielen Dank! Hannes
Hannes Vogelmann schrieb:
Am Mit, 23 Jun 2004, schrieb Bernd Obermayr:
Hannes Vogelmann schrieb:
Moin,
ich habe folgendes Problem:
Ich habe 2 Dateien die jeweils eine 2-reihige Tabelle enthalten, wobei die jeweils erste Reihe in beiden Tabellen gleich ist (forlaufender Index, 4095 Zeilen) und ich will diese zunächst nun in eine 3-reihige Tabelle überführen. Später muss durch einen mathematischen Formalismus aus den drei Reihen auch noch eine 4. Reihe generiert werden. Da die beiden Ausgangs-Dateien als Standart-output aus einem Messystem kommen, auf die stets der selbe Auswertungsalgorithmus angewendet werden soll brauche ich ein script, dass diese Dateien autmoatisiert verarbeiten kann und eine standartisierte Ausgangsdatei mit 4 Reihen erzeugt. Im Ergebnis sollte dann sowas wie
1. 2. 3. 4. Index Daten1 Daten2 Funktion(Index,Daten1,Daten2)
herauskommen.
Ich wollte es mit gawk realisieren. Allerdings ist mir nicht klar, wie man mit gawk Dateien zusammenführt. So habe ich die beiden Dateien erstmal sequentiell aneinandergehängt und wollte dann durch Verschieben des gwak-Parameters FNR die $2 von FNR+4095 auslesen, was aber so nicht hinhaut.
Vielleicht sollte man es besser gleich mit perl veruchen, aber damit kenne ich mich leider gar nicht aus.
Hat jemand eine Idee oder kann mir im groben aufzeigen, wie man da dran geht?
man join ;)
join file1 file2 | awk '{erg=$2*$3;printf("%-40s : %20.10f",$0,erg);}'
verblüffend einfach, aber macht genau das, was ich will ;-)) Da muss man auch erstmal draufkommen. Von joint hatte ich nie was gehört.
tststs Nicht 'joint', join ;) Tja manchmal hat man als alter unixer halt doch noch die Nase vorn ;)) Gruss bernd
Am Mit, 23 Jun 2004, schrieb Bernd Obermayr:
Hannes Vogelmann schrieb:
Am Mit, 23 Jun 2004, schrieb Bernd Obermayr:
Hannes Vogelmann schrieb:
Moin,
ich habe folgendes Problem:
Ich habe 2 Dateien die jeweils eine 2-reihige Tabelle enthalten, wobei die jeweils erste Reihe in beiden Tabellen gleich ist (forlaufender Index, 4095 Zeilen) und ich will diese zunächst nun in eine 3-reihige Tabelle überführen. Später muss durch einen mathematischen Formalismus aus den drei Reihen auch noch eine 4. Reihe generiert werden. Da die beiden Ausgangs-Dateien als Standart-output aus einem Messystem kommen, auf die stets der selbe Auswertungsalgorithmus angewendet werden soll brauche ich ein script, dass diese Dateien autmoatisiert verarbeiten kann und eine standartisierte Ausgangsdatei mit 4 Reihen erzeugt. Im Ergebnis sollte dann sowas wie
1. 2. 3. 4. Index Daten1 Daten2 Funktion(Index,Daten1,Daten2)
herauskommen.
Ich wollte es mit gawk realisieren. Allerdings ist mir nicht klar, wie man mit gawk Dateien zusammenführt. So habe ich die beiden Dateien erstmal sequentiell aneinandergehängt und wollte dann durch Verschieben des gwak-Parameters FNR die $2 von FNR+4095 auslesen, was aber so nicht hinhaut.
Vielleicht sollte man es besser gleich mit perl veruchen, aber damit kenne ich mich leider gar nicht aus.
Hat jemand eine Idee oder kann mir im groben aufzeigen, wie man da dran geht?
man join ;)
join file1 file2 | awk '{erg=$2*$3;printf("%-40s : %20.10f",$0,erg);}'
verblüffend einfach, aber macht genau das, was ich will ;-)) Da muss man auch erstmal draufkommen. Von joint hatte ich nie was gehört.
tststs Nicht 'joint', join ;) Tja manchmal hat man als alter unixer halt doch noch die Nase vorn ;))
ehemm,... join natürlich, aber meine Gedanken waren wohl gerade wo anders ;-). Eine Frage habe ich jetzt aber doch noch: mit printf macht awk keinen Zeilenumbruch und mit print funktioniert der Ausdruck "%-40s : %20.10f" nicht. Was der allerdings genau macht ist mir auch nicht klar, das 10f steht wohl für 10 Nachkomastellen wenn ich nicht irre aber das andere? cu Hannes
Hi Hannes, Hannes Vogelmann schrieb:
Eine Frage habe ich jetzt aber doch noch: mit printf macht awk keinen Zeilenumbruch und mit print funktioniert der Ausdruck "%-40s : %20.10f" nicht.
Das ist Absicht, bei printf() hast du die Möglichkeit selbst zu bestimmen wo der Umbruch hin soll "\n" ist ein lf "\r" ist ein cr
Was der allerdings genau macht ist mir auch nicht klar, das 10f steht wohl für 10 Nachkomastellen wenn ich nicht irre aber das andere?
man awk /The printf Statement %40s ist ein string mit 40 Zeichen, - macht left justify %20.10f ist der komplette formatstring für diese Variable, ja 10 NK Stellen Gruss Falk
Hannes Vogelmann schrieb:
ehemm,... join natürlich, aber meine Gedanken waren wohl gerade wo anders ;-).
Eine Frage habe ich jetzt aber doch noch: mit printf macht awk keinen Zeilenumbruch und mit print funktioniert der Ausdruck "%-40s : %20.10f" nicht. Was der allerdings genau macht ist mir auch nicht klar, das 10f steht wohl für 10 Nachkomastellen wenn ich nicht irre aber das andere?
Sorry, hab ich übersehen. häng einfach einen Zeilenumbruch dran: "%-40s : %20.10f\n" man awk und man bzw info printf sagt Dir mehr dazu. printf ist was andres als print. print gibt einfach nur das Argument bzw $0 mit einem Zeilenumbruch aus. printf gibt einen formatierten String aus. "%-40s : %20.10f\n" bedeutet: String 40 Zeichen linksbündig, Space : Space, Fliesskommazahl 20 Zeichen lang, 10 Nachkommastellen (rechtsbündig) und ein newline Zur Demo mal ein Script: ----8<---- #!/bin/bash cat <<EJ1 >/tmp/j1 l1 100.56 l2 220.34 l3 3111.44 EJ1 cat <<EJ2 >/tmp/j2 l1 4234.67890 l2 54.7823 l3 6.00888 EJ2 join /tmp/j1 /tmp/j2 | \ awk 'BEGIN { fmt="%-20s %15.8f %15.8f : %20.8f\n"; } { erg=$2*$3;printf(fmt,$1,$2,$3,erg); sj1+=$2; sj2+=$3; } END { printf( "--------------------------------------------" ); print "--------------------------------------------" printf(fmt,"Summen",sj1,sj2,sj1*sj2); }' ----8<---- Wichtig ist hierbei, dass Fliesskommazahlen den Punkt als Dezimaltrenner haben. Mit Komma mag awk nicht rechnen, kann sein, es ist möglich via locale etwas anderes vorzugeben. Damit hab ich mich aber noch nie befasst ;) HTH Gruss bernd
participants (7)
-
David Haller
-
Dominik Schopper
-
Falk Sauer
-
Falko Zurell
-
Ferdinand Ihringer
-
Hannes Vogelmann
-
Illuminatus@t-online.de