hash mit name aus variable vereinbaren ... kA ^^

Öhm joa... n richtiger Titel für den Threat is mir grad net eingefallen, aber naja...

Code:
$paketname::hashname{schluessel} = "wert"
Im Paket "paketname" soll in einem Hash mit dem Namen "hashname" der Schlüssel "schluessel" der Wert "wert" gesetzt werden.
Soweit ist das alles ja noch OK.

Jetzt würe ich gerne "hashname" und "schluessel" durch variablen tauschen.
also quasi so:
Code:
paketname::$hashname{$schluessel} = "wert"
Das funktioniert aber natürlich nicht.

Desswegen hab ichs mal so versucht:
Code:
${"paketname::$hashname"}{$schluessel} = "wert"
funktioniert auch nicht.

Der nächste Versuch:
Code:
package paketname;
$$hashname{$schluessel} = "wert"
will auch net so wie es soll,

und
Code:
pakage paketname;
${$hashname}{$schluessel} = "wert"
oder
Code:
package paketname;
${"$hashname"}{$schluessel} = wert
auch nicht...


Jemand ne Idee wie sich das anstellen lässt?

MFG - Keks :)
 
Langweilige Lösung:
Code:
my %newhash;
while(my ($key, $val) = each %hash) {
 delete($hash($key));
 $newhash{$val} = $key;
}

Tolle Lösung
Code:
%neuerhash = reverse %alterhash

Da das nur ausm Kopf ist, weiß ich nicht, ob das auf der gleichen Datenstruktur auch funktioniert, weil sonst kann das intern Mumpitz geben, wenn man nicht aufpasst (soll heissen, ist lange her, dass ich das verwendet hab, und da auch nicht auf die gleiche variable gemappt habe ...)
sollte eigentlich auch mit dem Befehl map gehen, wenn reverse nicht mag.

EDIT: ich habs gerade ausprobiert. Wenn du 2 gleichnamige SchluesselWERTE hast, geht der 2. verloren, das ist dann sogar egal ob du das auf denselben hash oder einen anderen abbildest.
Das ist aber wieder das generelle Problem, dass du auch bei Map haben wirst.
Am besten, du machst es nach der langweiligen methode in einen neuen hash, und resettest das ding im anderen paket

(Ich frag mich sowieso, warum du Variablen aus einem anderen Paket so radikal verändern willst, denn Objektorientierung und so widerspricht dir eigentlich, dass du das idr nicht willst, aber ... Perl => TIMTOWTDI => aber das ist dein Ding ....) :D
 
naja warum ich das mache...

Ich hab verschiedene Config's die von einem Script geparst werden.
Damit ich alle Config-Werte zentral, und immer im gleichen Muster habe will ich sie eben im Paket "CONFIG" in eiem Hash mit dem namen des Paketes, zudem die Config gehört speichern.
Die einzelnen Direktiven bekommen dann jeweils einen Schlüssel im Hash.

zB die Config von "MySQL" hat folgende Struktur:
Code:
HOSTNAME = localhost
DATABASE = datenbank
...

Dann wird in $CONFIG::MySQL{HOSTNAME} zB der Wert "localhost" zugewiesen.
Ich finde, das ist die bis jetzt beste, und übersichtlichste lösung die mir engefallen ist.

Wenn du eine bessere Idee hast, imemr her damit :)

MFG - Keks :)
 
Ich versteh immer noch nicht, warum du das dann umdrehen willst?
(btw: ich bin genau mit dem paket und den configvariablen auch auf so ne idee gekommen ;D)

"connect to $paket::hash{'user'}@$paket::hash{'domain'}".

Was willst du da noch gross umdrehen? Oder willst du einzelne Werte extrahiert umdrehen?
Ich mein ..
Code:
while(defined(<FILE>)) {
 ($key, $val) = split '=';
   # trailing/leading whitespaces gibts nich ..
   $paket::hash{$key} = $val;
   # unter vorraussetzung, dass es keinen key 2x gibt
}

ich versteh wirklich nicht, warum du das umdrehen willst *rätsel*
 
Ich finde, das ist die bis jetzt beste, und übersichtlichste lösung die mir engefallen ist.

Fuer solche Zwecke eignen sich auch sehr schoen simple hash arrays in einer zentralen config datei ;)

Ich verwalte so ca 35 unix server in nem eigenen backup system in einem solchen hash:

%HOST -> HOSTNAME1 -> KEY -> VALUE
-> KEY -> VALUE
-> KEY -> VALUE
HOSTNAME2 -> KEY -> VALUE
-> KEY -> VALUE
....

Das Hash liegt in einer Datei und wird einfach per require
eingebunden und somit hab ich zugriff darauf.
Den Parser so an Aenderungen anzupassen ist dann ein Kinderspiel.
 
Original von menace
Ich versteh immer noch nicht, warum du das dann umdrehen willst?
(btw: ich bin genau mit dem paket und den configvariablen auch auf so ne idee gekommen ;D)

Wieso umdrehen?
Ich glaub du hast das mit dem "druch Variablen tauschen" falsch verstanden ^^

Ich wollte lediglich im ersten codebeispiel das wort "hashname" durch die Variable "$hashname" und "schluesselname" durch die Variable "$schluesselname" tauschen,
damit ich die Hash-Einträge dynamisch erzeugen kann.

Es soll ja ein "Parser-Script" für alle Configs gelten, da weis ich also in Voraus nicht, welche Direktiven / Werte vorkommen werden.

Desshalb will ich einfach einen Zentralen Hash im Paket "config", mit dem Namen der Config, indem dann für jede Direktive in der Config ein Hash-Schlüssel angelegt, und der entsprechende Wert zugewiesen wird :)

heir mal 2 Config-Beispiele:

Code:
# MySQL-Config:
HOSTNAME = localhost
DATABASE = datenbank
Code:
# kA-Config:
DIREKTIVE1 = Wert
DIREKTIVE2 = Wert2

später existieren dann folgende Hash's:
Code:
%CONFIG::MySQL = (
  HOSTNAME => 'localhost',
  DATABASE => 'datenbank'
);

%CONFIG::kA = (
  DIREKTIVE1 => 'Wert',
  DIREKTIVE2 => 'Wert2'
);

Der Einfachkeit für den End-User halber, und zur Vermeidung von Kompilierungs-Fehlern habe ich mich für eine Text-Variente entschieden, da hier kein Perl-Code vorkommt, und so der "dumme" User nichts kaputt machen kann :)


Ein Weiteres Code-Beispiel zur erklärung:
Code:
# MySQL-Config
HOSTNAME = localhost
Daraus soll ein Hash erzeugt werden:
Code:
$CONFIG::MySQL{'HOSTNAME'} = 'localhost';

Das Problem ist, dass "MySQL", "HOSTNAME" und "localhost" variabel sein müssen.

Quasi sowas:
Code:
$CONFIG::$CONFIGNAME{$DIREKTIVE} = $WERT;

Wenn jetzt eine Config "HaBo" existieren würde, mit folgenden Einträgen:
Code:
# HaBo-Config
THREAT-ERSTELLER = keksinat0r

Soll folgender Hash erzeugt werden:
Code:
$CONFOG::HaBo{THREAT-ERSTELLER} = 'keksinat0r'

Es sollen also dynamisch Hash's, Schlüssel und Werte erstellt werden... je nach Config

MFG - Keks :)
 
Ah, jetzt verstehe ich was du gemeint hast. Schande über mein Haupt.
Also richtige Pakete kannst du so referenzieren, via $paketname::{'variable'} aber _Pakete_ (was in Perl Module sind) kannst du höchstens über XS/eval erzeugen, und das ist ziemlich hässlich. Und das willst du auch nicht.

Wenn du unbedingt die Doppelpunktschreibweise willst, kannst du ja Klassen machen, Hashvariablen generieren und diese via tie an die Klassen binden. Aber mal eine Frage: Warum keine Hashes in Hashes?

Code:
while(defined(my $line = <FILE>)) {
        chomp($line);
        if($line =~/^# /) {
                my ($a, $b) = split(' ', $line);
                $lasthash = $b;
                next;
        } else {
                my ($key, $val) = split('=', $line);
                # keine trailing/leading spaces
                # keine doppelten keys
                $inhalt{$lasthash}{$key} = $val;
        }
}

du kannst dann mit $inhalt{"MYSQL"}{"HOST"} die IP ausgeben. wenn in der config bei host eine ip steht :)
Die tie-Variante (für die Doppelpunkteschreibweise) hab ich grad nicht im kopf, wenn's sein muss, kann ich morgen mal nachgucken ..
 
re

Also die Doppelpunktschreibweise bekommt man auch ohne Klassen und eval hin...

Code:
#!/usr/bin/perl -w
use strict;

package Test;
our %hash = (wert1 => 'eins', wert2 => 'zwei');


package main;
for (0..1) {
  print $Test::hash{'wert1'} ."\n";
  $Test::hash{'wert1'} = 'hundert';
}

MfG

edit:
Du kannst jetzt naetuerlich auch Variablen benutzen...
Code:
package main;
my $variable = 'wert1';
print $Test::hash{$variable} ."\n";
$Test::hash{$variable} = 'hundert';
print $Test::hash{$variable} ."\n";
geht auch
 
dazu muss aber die Variable hash schon in der Klasse davor existieren und das tut sie ja nicht unbedingt. die config ist ja beliebig variabel.
so zumindest habe ich ihn verstanden.
Wie willst du zb die Variable $variable selbst in deine klasse schieben, dass sie danach mittels $klasse::variable abrufbar ist?
 
Die Erklärung gestaltet sich schwieriger als gedacht... ^^

Ich versuchs mal als pseudo-code:
Code:
$CONFIGNAME <= name_der_configdatei;

Erstelle in Paket "CONFIG" einen Hash mit namen "$CONFIGNAME";

solange $ZEILE < Zeilenanzahl_der_config mache:
  $Zeileninhalt <= Zeileninhalt der Zeile $ZEILE;
  ($Direktive,$Wert) <= spalte Zeileninhalt bei Zeichen "=" auf;
  erstelle in dem erstellten Hash einen Schlüssel mit namen "$Direktive" und speichere darin $Wert;
  $Zeile++;
solange_ende;

--------------

Es gibt mehrere Configs, jede config ist gleich aufgebaut, immer "Direktive = Wert"
jetzt soll das Parser-Script jede config die ihm übergeben wird einlesen.
Für jede Config soll im Paket "CONFIG" ein eigener Hash erstellt werden, dessen name sich aus dem Configname ergibt.
darin wiederum soll für jede Direktive in dem Hash ein Schlüssel erstellt werden, dem der Wert nach dem "=" zugewiesen wird.

--------------

zB in der Configdatei "HaBo.conf" steht folgendes:
Code:
Threat-ersteller = keksinat0r
Datum = 18.09.2007

jetzt soll das Parser-Script einen Hash %CONFIG::HaBo anlegen, und darin die Schlüssel "Threat-ersteller" und "Datum" anlegen.
Diesen wiederum die entsprechenden Werte (keksinat0r und 18.09.2007) zuweisen.

in einer weiteren Config namens "MySQL.conf" steht zB
Code:
Hostname = localhost
Database = keks

Jetzt soll das Parserscript einen weiteren Hash %CONFIG::MySQL anlegen und in dessen Schlüsseln "Hostname" und "Database" die entsprechenden Werte speichern.

Dann gibt es wieder eine Configs, usw usf...

--------------

Es soll also für jede Config die gefunden wird ein eigener Hash angelegt werden, der den Namen der Config trägt.
Das Problem sind nicht die Schlüssel, oder Werte, sondern die Namen der Hash's.

Die Hashs können ja theoretisch jeden x-beliebigen Namen haben, je nach Name der Config.

Wenn es jetzt noch eine Config "Kein-Plan.conf" gäbe, soll auch noch der Hash %CONFIG::Kein-Plan" erstellt werden

--------------

Code:
      CONFIGNAME  DIREKTIVE  WERT
          |       |           |
          v       v           v
$CONFIG::MySQL{'HOST'} = 'localhost';

----------------

@menace exakt.
ich will in dem paket "CONFIG" für jede Config-Datei die gefunden wird einen Hash mit namen der Config erzeugen, und diesem die entsprechenden Config-Daten in Schlüssel unf Wert zuseisen.

Variablen/Hash's in anderen Paketen erzeugen ist kein problem, einfach mittels $paket::variable = 'wert' zuweisen :)

MFG - Keks :)
 
Variablen/Hash's in anderen Paketen erzeugen ist kein problem, einfach mittels $paket::variable = 'wert' zuweisen
Hoe? Imo belegst du damit bloss eine Variable einer Klasse mit einem Wert. Aber erzeugen tust du die damit nicht. das glaube ich jedenfalls nicht ohne strict+warnings-beispiel.

Zum anderen, du willst wohl tie (siehe man perlfunc) verwenden, wer's mag... Ich finds irgendwie komisch, einer Klasse im Nachhinein ein Attribut aufzudrücken. Das hat so gar nix von Objektorientierung an sich, noch nicht mal guten Programmierstil imo. Aber ich bin ehrlich auf deine Lösung gespannt.
 
naja es dient der Übersicht...

so sind alle configs zentral in dem Paket "CONFIG" und jede Config hat in diesem Paket ihren eigenen Hash, indem die ganzen Direktiven und Werte gespeichert sind :)

Bis jetzt hab ich nur eine sehr unschöne Lösung gefunden,
undzwar erzeuge ich zZ ( bis ich eine gescheite Lösung finde ) einfach ein weiteres Perlmodul, dass die Hash-Werte anlegt:
Code:
#!/usr/bin/perl

use warnings;
use strict;
use Cwd;


my $buffer = "buffer".time();

open(BUFFER,">>$buffer.pm");
  print BUFFER "package CONFIG;\nuse strict;\n";

  foreach my $config ( glob("configs/*.conf") ){
    open(CONFIG,$config);

      $config =~ s/(^.*\/|\.conf$)//ig;
      print BUFFER "our \%$config;\n";

      foreach( <CONFIG> ){
        $_ =~ s/(^\s*|(\#.*)?\s*$)//g;
        unless( $_ =~ /^$/ ){
          my ($directive,$value) = split( /\s*=\s*/ , $_ );
          print BUFFER "\$$config\{\"$directive\"\} = \"$value\";\n";
        }
      }

    close(CONFIG);
  }

close(BUFFER);

require(getcwd()."/$buffer.pm");

foreach( keys %CONFIG::test ){
  print "$_ -> $CONFIG::test{$_}\n";
}

Dazu folgende Config in "./configs/" :
test.conf:
Code:
bla = blubb
blubber = blah
möp = keks

usw...

Es ist keine schöne Lösung, aber sie funktioniert...
Dieses "Tie" blick ich net so ganz, aber ma sehn ob ich ne bessere Lösung, wie die jetzige finde...

MFG - Keks :)

PS: Gott.. scho das 4. mal editiert... scheiß Rechtscheibfehler :D
 
Bis jetzt hab ich nur eine sehr unschöne Lösung gefunden,
undzwar erzeuge ich zZ ( bis ich eine gescheite Lösung finde ) einfach ein weiteres Perlmodul, dass die Hash-Werte anlegt:

Wieso nimmst du nicht einfach ein globales hash (siehe meinen vorigen Post)?

Deine LOesung ist in der Tat mehr als unknusprig ;)
 
Wie gesagt, die Lösung ist nur vorläufig. - Hauptsache es funktioniert estmal.

Warum kein Globales hash...
Naja, natürlich würde das gehen, zB $CONFIG::CONFIG{'MySQL'}{'username'}, aber es wäre eben schöner wenn es $CONFIG::MySQL{'username'} sein würde :)

Ich finde das einfach übersichtlicher, und das doppelte "CONFIG" fällt weg :)
Bei dem zweiten sieht sofort, das ist der Config-Eintrag "username", und zwar aus der MySQL-Config.

Ich könnte zwar auch das Modul in jedes Sub-Modul des Hauptscriptes mittels "use" einbinden und den Hash via "Export" in das neue Paket exportieren, allerdings ist das umständlich und außerdem:

Wenn ich mir einmal etwas in den Kopf gesetzt habe will ich das auch durchziehen....
Und ich werde nicht aufgeben, bis ich die Lösung für mein Problem gefunden habe :D

Heut abend setz ich mich nochma dran und probier bissel rum...
Vielleicht fällt mir ja nochwas ein ^^

MFG - Keks :)
 
Ich versteh immer noch nicht, warum du dich an dem Syntaxunterschied
$CONFIG::MYSQL{'foo'} gegen $CONFIG{'MYSQL'}{'foo'} aufhängst.

Zumal letzteres ja leicht zu erreichen ist. Hashes kannst du auch einbinden, wie auch schon Gulliver gezeigt hat.
Und wieso will man Perlmodule erzeugen? Du hast eine Datei und ein Perlmodul, das eine funktion enthaelt, dass aus der Datei den Hash macht. aber wie gesagt, ich bin gespannt ^^
 
Um einen Hash "einbinden" zu können muss er sertmal existieren!
Und genau da ist das Problem.

Es ist eben nicht $CONFIG{'mysql'}, da das Modul, indem der Hash liegt nicht gleich dem Modul ist, indem der Hash benötigt wird.
Es gibt ein Haupt-Script, das in mehrere Module unterteilt ist.

In einem anderen Modul wäre es dann nichtmehr $CONFIG{'mysql'} sondern $main::CONFIG{'mysql'} oder $config::CONFIG{'mysql'}.
Jenachdem in welchem Paket der Hash vereinbart wird...

Die Hashs sollen ja variabel angelegt werden.
Sodass %CONFIG::MySQL überall gültig ist.

Im Paket "Blah" müset ich $main::CONFIG{'MySQL'}{'username'} aufrufen.
Wenn ich meien Methode benutzte rufe ich $CONFIG::MySQL{'username'} auf...

Sicher... Ich könnte einfach hingehen und im Hauptscript einen Hash %CONFIG vereinbaren und ihn überall via %main::CONFIG aufrufen...
Ich hab mir das aber so in den Kopf gesetzt, und ich will das so haben wie erwähnt.
Es ist schöner, übersichtlicher und weniger Scheibarbeit beim aufrufen des Hash's.

---

Das "Modul-Erstellungs-Script" nutze ich ( wie desöfteren erwähnt ) provisorisch, bis ich eine alternative gefunden habe.
Es ist zZ die einzige funktionierende Lösung, und veranschaulicht auh nocheinmal was ich genau erreichen will.

---

Ich finds ja toll, dass ihr mir alternativen anbietet, aber ich will nunmal die von mir vorgestellte Lösung :)

MFG - Keks :)
 
Zurück
Oben