simu73: Einem Skalar einen Wert aus externer Datei hinzufügen

Hallo gute Geister!

Ich bin an sich kompletter Anfänger auf dem Gebiet CGI / Perl, habe aber nach 2 durchgemachten Nächten das Ziel fast erreicht. Nun kreise ich seit ein paar Stunden in Sichtweite der Ziellinie. Irgendwie klappt der letzte (entscheidende) Schritt nicht, obschon der eigentlich einfach sein müsste.
Konkret: Ich möchte einem Skalar einen Wert zuweisen, welcher in einer externen Datei gespeichert ist. Vermutlich könnte das ungefähr so aussehen:

  
open(AKTHLES,"<","AktuellH.txt") || die "Datei nicht gefunden";  
my %Aktuelle_Daten = <AKTHLES>;  
close(AKTHLES);  
  
my $GrafTel = my "$Aktuelle_Daten('GrafTel')";  

Das einzige was ich nach den Experimenten mit Sicherheit sagen kann, ist dass die externe Datei an sich aufgerufen und ausgelesen werden kann.

Ich habe unzählige Varianten (Komma, Klammern, Anführungszeichen an verschiedensten stellen) durchprobiert, ebenso diverse Notationen der Werte in der externen Datei.
Eine denkbare Alternative wäre auch, die "fertigen" Skalare (inkl. Wert) in der externen Datei zu speichern. Also:

my $GrafTel = "zu.png"  
my $GrafBob = "zu.png"  

Aber auch so habe ich das Problem, diese dann in das Skript zu "importieren".

Das erstaunliche ist, dass ich bis auf obenstehendes Problem alles funktioniert (zumindest auf dem lokalen Indianer und in der vorliegenden - ungeschminkten - "Rohfassung").

Hintergrund Infos:

Der Quellcode der verschiedenen beteiligten Dateien ist hier zu finden. Da ich bisher offline arbeitete und somit die Files noch nicht für diesen "Lagerort" angepasst habe, ist die Dateiendung ".pl" durch ".txt" ersetzt (nur "Aktuell" und "AktuellH" sind auch sonst ".txt"-Dateien):

Wenn ich nix falsch gemacht habe, sollten in dieser Datei die entsprechenden Werte (mit zugehörigen Namen) als Hash vorliegen:
http://teleskinods.ch/test/source/AktuellH.txt

Hier die Liste mit fertigen Skalaren (Alternative):
http://teleskinods.ch/test/source/Aktuell.txt

Das Script zum erstellen des HTML-Formulars, welches die Werte erzeugt:
http://teleskinods.ch/test/source/Aendern.txt

Das Script, welches die Formulardaten in die ".txt"-Dateien speichert (und mir vorläufig die Daten zur Kontrolle auch anzeigt):
http://teleskinods.ch/test/source/Speichern.txt

Das Script, welches schliesslich den HTML-Code erzeugt, welcher in die website eingebunden wird:
http://teleskinods.ch/test/source/Anzeigen.txt

Ein Experimentier-Script zum Auslesen der Daten aus der ".txt"-Datei:
http://teleskinods.ch/test/source/Auslesen.txt

Der Vollständigkeit halber die ganze Website, allerdings noch ohne die CGI-Basteleien:
http://teleskinods.ch/test/index.shtml

  1. Irgendwie klappt der letzte (entscheidende) Schritt nicht, obschon der eigentlich einfach sein müsste.

    Was klappt nicht? Steht was im Errorlog? Benutze Data::Dumper, um Dir den Inhalt von Arrays oder Hashes anzeigen zu lassen.

    open(AKTHLES,"<","AktuellH.txt") || die "Datei nicht gefunden";
    my %Aktuelle_Daten = <AKTHLES>;
    close(AKTHLES);

    my $GrafTel = my "$Aktuelle_Daten('GrafTel')";

      
    Der Inhalt einer Textdatei wird zeilenweise geliefert. Damit kannst Du ihren Inhalt entweder nur einem Skalar (aktuell gelesene Zeile) oder einem Array (alle Zeilen auf einmal) zuweisen. Um eine andere Struktur zu bekommen, musst Du die eingelesenen Daten vorher bearbeiten. So, wie Du hier vorgehst, wird der gesamte Inhalt als Hashkey verwendet, weshalb der Rest vor den Baum gehen muss.  
      
    Weise also den Dateiinhalt einem Skalar zu und splitte diesen, denn erst dann kannst Du Deinen Hash füllen.  
      
    
    > Eine denkbare Alternative wäre auch, die "fertigen" Skalare (inkl. Wert) in der externen Datei zu speichern.  
      
    Du kannst das ganze auch in Textdateien auslagern, welche kleine Perlschnipsel enthalten, die Du mittels do und Konsorten einbindest.  
      
    
    > Wenn ich nix falsch gemacht habe, sollten in dieser Datei die entsprechenden Werte (mit zugehörigen Namen) als Hash vorliegen:  
    > <http://teleskinods.ch/test/source/AktuellH.txt>  
      
    Nein, Textdateien können keine Variablen enthalten.  
      
    Siechfred
    
    -- 
    Chancengleichheit bedeutet nicht, dass jeder einen Apfel pflücken kann, sondern dass der Zwerg eine Leiter bekommt.
    
    1. Besten Dank erstmal für die schnellen Antworten. Damit habe ich wohl wieder ein paar Stunden Lern- und Experimentierstoff.
      Falls ich nicht doch vorher zur Abwechslung etwas Schlaf brauche ;-)

      Melde mich dann wieder, wenn ich sehe ob's geholfen hat.

      LG Simu.

  2. Konkret: Ich möchte einem Skalar einen Wert zuweisen, welcher in einer

    externen Datei gespeichert ist. Vermutlich könnte das ungefähr so aussehen:

    open(AKTHLES,"<","AktuellH.txt") || die "Datei nicht gefunden";
    my %Aktuelle_Daten = <AKTHLES>;

    Ein Hash ist ein gutes Speicerhmedium, aber diese Art der Zuweisung ist extrem riskant.
    Ein Hash ist kein Scalar, sondern ein Assoziativer Array.
    Wenn du wirklich die ganze Datei in einem einzigen Scalar speichern willst
    my $scalar = <Filehandle>;

    close(AKTHLES);

    my $GrafTel = my "$Aktuelle_Daten('GrafTel')";

    use warnings hätte dir hier eine Meldung hinterlassen.
    Wenn du ein hashelement ansprechen willst, verwendest du
    $hash{key}     {} statt ()

    
    >   
    > Das einzige was ich nach den Experimenten mit Sicherheit sagen kann, ist dass die externe Datei an sich aufgerufen und ausgelesen werden kann.  
    >   
    > Ich habe unzählige Varianten (Komma, Klammern, Anführungszeichen an verschiedensten stellen) durchprobiert, ebenso diverse Notationen der Werte in der externen Datei.  
    > Eine denkbare Alternative wäre auch, die "fertigen" Skalare (inkl. Wert) in der externen Datei zu speichern. Also:  
    > ~~~perl
    
    my $GrafTel = "zu.png"  
    
    > my $GrafBob = "zu.png"  
    > 
    
    

    Aber auch so habe ich das Problem, diese dann in das Skript zu "importieren".

    Das erstaunliche ist, dass ich bis auf obenstehendes Problem alles funktioniert (zumindest auf dem lokalen Indianer und in der vorliegenden - ungeschminkten - "Rohfassung").

    Ok. ich weiss jetzt, was du willst.
    Nimm an, dein File sieht so aus:

    Key1=Wert1\n

    irgend ein Kommentar

    Key2=Wert2\n
    ...
    Key3=Wert3\n

    Um diese Daten in einem Perl Variable zu speichern ist ein Hash geeignet.

    my %Data;
    open(FH,"<","DB.txt") or die ('Kein Zugriff DB File $!')
    #Zeilenweise auslesen
    while(<FH>){
      # solange ich eine Zeile bekomme
      # durchsuche die Zeile nach (key)=(wert) und speichere sie in %Data
      $_ =~ /^(.+?)=(.*)/ and $Data{$1} = $2;
    }
    close(FH);

    Jetzt kannst du sagen:
    $Data{Name} eq 'Peter' and do_something();

    mfg Beat

    --
    Woran ich arbeite:
    X-Torah
    ><o(((°>           ><o(((°>
       <°)))o><                     ><o(((°>o
  3. Sorry für die späte Rückmeldung. Nach der intensiven Startphase mit 48 Std. fast pausenlos an der Kiste gönnte ich mir auch mal Schlaf, 'ne gute Party und heute sogar "normale" Arbeit.
    Aber es funzt! Nach dem Durchbruch am Freitag Abend habe ich seither aus lauter Freude am gelernten noch weiter experimentiert, die Scripte ein bisschen aufgeräumt etc.

    Die geschweiften Klammern waren natürlich ein Teil der Lösung:

    Wenn du ein hashelement ansprechen willst, verwendest du
    $hash{key}     {} statt ()

    Der eigentliche Stolperstein lag aber im ".txt"-File. Ich habe da die Werte (und zeitweise auch die Keys) alle fein säuberlich in Anführungszeichen gesetzt, wie ich dies in den Beispielen auf Selfhtml und anderswo gesehen habe. Also z.B.:

      
    "GrafBoule" = "off.png"  
    "Schnee" = "45"  
    
    

    Anscheinend gilt dies nur für die direkte Zuweisung von Werten. Geklappt hat's schliesslich so (hab erst hinterher gesehen, dass Beat auch hier ein passendes Beispiel geliefert hat):

      
    GrafBoule=off.png  
    Schnee=45  
    
    

    Auch diesen Code benutzte ich schliesslich:

      
    my %Aktuelle_Daten;  
    open(FH,"<","DB.txt") or die ('Kein Zugriff DB File $!')  
    #Zeilenweise auslesen  
    while(<FH>){  
      # solange ich eine Zeile bekomme  
      # durchsuche die Zeile nach (key)=(wert) und speichere sie in %Aktuelle_Daten  
      $_ =~ /^(.+?)=(.*)/ and $Aktuelle_Daten{$1} = $2;  
    }  
    close(FH);  
    
    

    Und nun konnte ich mit meiner ursprünglichen Idee weiterfahren:

      
    my $GrafBoule = my "$Aktuelle_Daten('GrafBoule')";  
    my $Schnee = my "$Aktuelle_Daten('Schnee')";  
    
    

    Nun ist sicher nicht alles perfekt, insbesondere muss ich die Sache noch gegen unbefugte Zugriffe schützen und könnte noch Filter gegen "falsche" (Sonder-)Zeichen einbauen. Aber in Anbetracht der Tatsache, dass ich letzten Mittwoch noch nicht die leiseste Ahnung von CGI's und Perl hatte, ist meine Freude momentan schon recht gross.

    Ich hab auch gesehen, dass es wohl noch verschiedenste Lösungswege gegeben hätte - vielleicht auch ganz einfache. Hab leider nicht kapiert, wie Siechfred dies meinte (hab nur "do while" u.ä. gefunden):

    »»Du kannst das ganze auch in Textdateien auslagern, welche kleine Perlschnipsel enthalten, die Du mittels do und Konsorten einbindest.

    Falls da einem Möglichkeit analog zum einbinden von Dateien wie mit SSI (.shmtl mit .inc Bausteinen) bestehen sollte, sagt mir das jetz auf keinen Fall mehr!

    Falls jemand das Resultat anschauen möchte (nebst der funktionierenden Variante sind zum Teil auch noch alternative Versuche zu erkennen):

    http://teleskinods.ch/test/aendern.shtml

    Rumspielen ist erlaubt (natürlich einfach ohne böse Absichten).

    Zur Ansicht des Quellcodes habe ich die ".pl" Scripte hier noch als ".txt" Files gespeichert:

    Das Script zum erstellen des HTML-Formulars, welches die Werte erzeugt:
    http://teleskinods.ch/test/source/Aendern.txt

    Das Script, welches die Formulardaten in die ".txt"-Dateien speichert (und mir vorläufig die Daten zur Kontrolle auch anzeigt):
    http://teleskinods.ch/test/source/Speichern.txt

    Das Script, welches schliesslich den HTML-Code erzeugt, welcher in die Website eingebunden wird:
    http://teleskinods.ch/test/source/Anzeigen.txt

    Ein Experimentier- und Kontroll-Script zum Auslesen der Daten aus der ".txt"-Datei:
    http://teleskinods.ch/test/source/Auslesen.txt

    Die "Original" (d.h. aktuell verwendete) Textdatei zum speichern der Variabeln:
    http://teleskinods.ch/test/cgi-bin/AktuellH.txt

    Danke nochmals für die Hilfe.
    Liebe Grüsse. Simu.

    1. Und nun konnte ich mit meiner ursprünglichen Idee weiterfahren:
      [code lang=perl]
      my $GrafBoule = my "$Aktuelle_Daten('GrafBoule')";

      1. Du kopierst eine Variable? warum?
         Merke: Auf den Inhalt vieler Hashkeys kannst du in einem Rutsch
         zugreiffen.
         Viele Scalare kannst du nicht einfach abarbeiten.

      2. Ist das
             my
         in
             my "$Aktuelle_Daten('GrafBoule');
         schlich falsch. Was willst du damit deklarieren?
         wenn
              $var
         den text
             "hallo welt"
         enthält dann wird bei
             "some text with $var"
         zuerst der Inhalt interpoliert zu
             "some text with hallo welt"
         welches du dann deklarieren willst mit
              my "some text with hallo welt"
         ?????
         konsultiere deine Errorlogs über Warnings an dieser Stelle.

      3. ist es blödsinnig
             "$var"
         zu schreiben, wenn
             $var
         genügt.

      Falls man überhaupt Variablen in eine neue Variable kopiert,
         dann so

      my $a_new_variable = $old_variable;

      Nun ist sicher nicht alles perfekt, insbesondere muss ich die Sache noch gegen unbefugte Zugriffe schützen und könnte noch Filter gegen "falsche" (Sonder-)Zeichen einbauen.

      Mache Filter für erlaubte Zeichen, nicht gegen falsche.

      Aber in Anbetracht der Tatsache, dass ich letzten Mittwoch noch nicht die leiseste Ahnung von CGI's und Perl hatte, ist meine Freude momentan schon recht gross.

      mfg Beat;

      --
      Woran ich arbeite:
      X-Torah
         <°)))o><                     ><o(((°>o
      1. Und nun konnte ich mit meiner ursprünglichen Idee weiterfahren:

        my $GrafBoule = my "$Aktuelle_Daten('GrafBoule')";

        1. Du kopierst eine Variable? warum?
             Merke: Auf den Inhalt vieler Hashkeys kannst du in einem Rutsch
             zugreiffen.
             Viele Scalare kannst du nicht einfach abarbeiten.

        Ich habe die Keys und Werte aus dem Eingabeformular zentral in der ".txt"-Datei abgespeichert, um dann mit verschiedenen Scripts darauf zugreifen zu können. (Vielleicht habe ich mit dieser Idee unter anderem den Begriff "objektorientiertes Programmieren" falsch interpretiert).
        Dass ich dann den Inhalt des Hashkeys noch in eine neue Variable kopiere, liegt daran, dass ich den den Script-Teil für die Ausgabe mit den entsprechenden Variabeln zuerst erstellt habe und erst nachher versucht habe, die entsprechenden Werte zu importieren.
        Im Nachhinein sehe ich auch, dass
        [code lang=perl]
        some Text $Aktuelle_Daten('GrafBoule') mehr Text

        die direktere Lösung als  
        ~~~perl
          
        some Text $SGrafBoule mehr Text
        

        wäre.
        Ist wohl ein Anfängerfehler (habe von der falschen Seite her gelernt), hat aber immerhin den positiven Nebeneffekt, dass der Teil für die Ausgabe des HTML-Codes (zumindest für meine Augen) etwas übersichtlicher ist.

        1. Ist das
                 my
             in
                 my "$Aktuelle_Daten('GrafBoule');
             schlich falsch. Was willst du damit deklarieren?
             wenn
                  $var
             den text
                 "hallo welt"
             enthält dann wird bei
                 "some text with $var"
             zuerst der Inhalt interpoliert zu
                 "some text with hallo welt"
             welches du dann deklarieren willst mit
                  my "some text with hallo welt"
             ?????
             konsultiere deine Errorlogs über Warnings an dieser Stelle.

        Sorry, da ist schlicht ein Fehler beim Schreiben des Postings passiert. Im Script steht

        my $GrafBoule = $Aktuelle_Daten{GrafBoule};  
        
        
        1. ist es blödsinnig
                 "$var"
             zu schreiben, wenn
                 $var
             genügt.

        Falls man überhaupt Variablen in eine neue Variable kopiert,
           dann so

        my $a_new_variable = $old_variable;

        Wenn schon Fehler, denn schon: Ebenfalls nur falsch ins Posting übertragen.

        Mein Murks mit den Anführungszeichen betraf die "rohen" Werte in der ".txt"-Datei und kommt von der falschen Interpretation von solchen (in anderem Kontext korrekten) Beispielen:

          
        my $Text = "Hallo Welt";  
        my %Daten = ("Name","Jana","Alter",23,"Ort","Berlin");  
        
        

        Nun ist sicher nicht alles perfekt, insbesondere muss ich die Sache noch gegen unbefugte Zugriffe schützen und könnte noch Filter gegen "falsche" (Sonder-)Zeichen einbauen.

        Mache Filter für erlaubte Zeichen, nicht gegen falsche.

        Aber in Anbetracht der Tatsache, dass ich letzten Mittwoch noch nicht die leiseste Ahnung von CGI's und Perl hatte, ist meine Freude momentan schon recht gross.

        mfg Beat;

        Merci für das wache Auge und die weiteren Tipps.
        Liebe Grüsse. Simu.