Joinen von Tabellenartiger Daten

- perl
Hallo zusammen,
wie joined man am besten die Ausgaben zweier Befehle nach einem bestimmten Wert? Ich möchte ein kurzes Beispiel geben, welches allerdings nur auf einem Linux bzw. Unixsystem nachvollzogen werden kann.
Zunächst einmal die zwei Befehlsausgaben, die ich joinen möchte.
Befehl 1: sar -x ALL 1 1
Befehl 2: ps -ef
Beide Ausgaben möchte ich über die PID joinen, was sinnvoller Weise auch nur über diese Spalte funktioniert. Von beiden Ausgaben möchte ich dann nur bestimmte Werte zusammanführen. Von der sar Ausgabe beispielsweise die System- und User-Auslastung und der Anteil der Swap-Belegung. Von der ps Ausgabe möchte ich hierzu den Owner des Prozesses, die PID sowie die PPID und das Kommando übernehmen. Alles einmal in einer vordefinierten Reihenfolge zusammengeführt soll dann nur noch eine Ausgabe erfolgen.
So schaut _mein_ wirklich grässlichen Code bislang aus:
Zunächst zum Verständnis meiner Variablen etc. :
Jedes Values besitzt zwei Werte Der erste Wert gibt die gewünschte Zielposition an, der zweite Wert gibt die Position (Spalte) an, in der der Wert in der Befehlsausgabe steht.
sPsPid zum Beispiel ist der Alias für die PID und der Wert befindet sich an der zweiten (0 1) Stelle in der ps -ef Ausgabe.
my $v = {
"sPsInfo" => {
"Command" => "sar -x ALL 1 1",
"Values" => {
"sPsTime" => "1,0",
"sPsPid" => "2,1",
"sPsMinorFaults" => "5,2",
"sPsMayorFaults" => "6,3",
"sPsUser" => "7,4",
"sPsSystem" => "8,5",
"sPsCpuNumber" => "9,7",
},
},
"PstInfo" => {
"Command" => "ps -ef",
"Values" => {
"PstOwner" => "4,0",
"PstPid" => "2,1",
"PstPPid" => "3,2",
"PstStartUp" => "10,6",
"PstDescription" => "11,7",
},
},
};
Und hier der Ausschnitt meines Joins:
my $asps = [ qx{sar -x ALL 1 1} ];
my $hsps = {};
# zunächst verfrachte ich die gesamte Ausgabe in einen Hash mit der PID als Schlüssel
foreach (@{$asps}) {
next if /^$/;
s/\t/ /g;
s/ */ /g;
last if /^(Durch|Avera)/;
chomp;
my ($pos,$col) = split /,/, $v->{sPsInfo}->{Values}->{sPsPid};
my $pid = (split / /, $_)[$col];
$hsps->{$pid} = $_;
}
my $apst = [ qx{ps -ef} ];
my $hpst = {};
# hier verfrachte ich die Ausgabe ebenfalls in einen Hash mit der PID als Schlüssel
foreach (@{$apst}) {
next if /^$/;
s/\t/ /g;
s/ */ /g;
chomp;
my ($pos,$col) = split /,/, $v->{PstInfo}->{Values}->{PstPid};
my $pid = (split / /, $_)[$col];
$hpst->{$pid} = "$_";
}
# nun joine ich den ganzen Kram, in dem ich einen der beiden Hashes
# in einer Schleife durchlaufe und die gewünschten Werte wiederrum
# in ein zweidimensionales Array schiebe. Der Index des zweiten
# Arrays ist gleichbedeutend mit der gewünschten Zielposition.
my $apos = [];
foreach my $key (keys %{$hsps}) {
if (defined $hpst->{$key}) {
foreach my $spsval (keys %{$v->{sPsInfo}->{Values}}) {
my ($pos,$col) = split /,/, $v->{sPsInfo}->{Values}->{$spsval};
push @{$apos->[$pos]}, (split / /, $hsps->{$key})[$col];
}
foreach my $pstval (keys %{$v->{PstInfo}->{Values}}) {
next if $pstval eq "PstPid";
my ($pos,$col) = split /,/, $v->{PstInfo}->{Values}->{$pstval};
push @{$apos->[$pos]}, (split / /, $hpst->{$key})[$col];
}
}
}
# zu guter letzt die Ausgabe... wohin auch immer...
my $oc = @{$apos};
my $ic = @{$apos->[1]};
for (my $o = 0 ; $o < $ic ; $o++) {
for (my $i = 1 ; $i < $oc ; $i++) {
print $CLIENT " " if $i > 1;
print $CLIENT "$apos->[$i]->[$o]";
}
print $CLIENT "\n";
}
Meine eigentliche Frage ist nun: es gibt da doch so eine geniale Schwartzsche Transformation zum Sortieren von mehrdimensionalen Arrays, die auch in mehreren meiner Jobs Verwendung findet. Gibt es solch ein Konstrukt auch zum Joinen von Tabellenartiger ausgaben?
Oder was könnte man alles an meiner Vorgehensweise bemängeln. Hoffentlich nicht allzu viel :-)
Bis dann.
Greez,
opi