Gustl: DynamicVariablen in Perl interpretieren, ähnlich JS eval?

hi, wie ersetze ich die 1 in $liste1[0] dynamisch?

[code lang=perl]for ($i .. $i++)  
{  
  if ($liste $i [0] == bla) { machwas }  
  ...  
}
~~~[/code]  
  
- Gustl
  1. Hallo,
    eval() gibt es auch in Perl.

    Die Verwendung ist aber problematisch, weil man dadurch sehr leicht Lücken in Programme baut, über die beliebiger Code ausgeführt werden kann ("eval is evil") - man sollte es daher nur verwenden, wenn 100%tig sicher gestellt werden kann, dass der Code, der von eval ausgeführt wird, nie etwas enthalten kann, was man ggf. nicht möchte.

    In Deinem Fall würde ich daher eher ein zweidimensionales Array vorschlagen.

    Hope that helps.

    Viele Grüße,
    Jörg

    1. Hallo,
      eval() gibt es auch in Perl.

      hi, ja weiss ich. ich check nur nicht wie man es einsetzt. könntest du mir das kurz beschreiben anhand eines einfachen beispiels?

        
        
      my $i = 3;  
        
      my $var$i = "variable name \$var3";  
        
      my eval("$variable$i"); ???  
        
      if ( eval("$variable$i") > pleite ) {..} ???
      

      ich checks nicht.

      wieso kann man nicht einfach my $hund{$i} schreiben oder so ähnlich. eine einfache schreibweise für das interpretieren dynamischer variablen eben, das wirds doch wohl geben.

      in meinem fall läuft eine schleife in einer anderen, und beide schleifen müssen variablen dynamisch erzeugen und verarbeiten. in der inneren schleife muss ich gleich 2 dynamische variablen erzeugen und mit einer dynamischen aus schleife 1 vergleichen. wer soll da noch mit einem mehrdimensionalen array durchblicken. ist so schon verzwickt genug.

      ich hab das selbe unter JS am laufen. da klappt das recht gut mit eval.

      • Gustl
      1. Hi,

        wieso kann man nicht einfach my $hund{$i} schreiben oder so ähnlich. eine einfache schreibweise für das interpretieren dynamischer variablen eben, das wirds doch wohl geben.

        $hund{$i} kannst du doch schreiben… wenn %hund ein Hash ist. Innerhalb des Hashes darf es beliebige Elemente als Values geben, z.B. auch Array-Referenzen.

        $hund{$i} = [ 0, 1, 2 ];  
        print $hund{$i}[1]; # gibt 1 aus
        

        Bis die Tage,
        Matti

        1. $hund{$i} kannst du doch schreiben… wenn %hund ein Hash ist. Innerhalb des Hashes darf es beliebige Elemente als Values geben, z.B. auch Array-Referenzen.

          $hund{$i} = [ 0, 1, 2 ];

          print $hund{$i}[1]; # gibt 1 aus

          
          >   
          > Bis die Tage,  
          > Matti  
            
          hi matti :-)  
            
          ich spring zu zeit ständig zwischen perl, js, php, css und ajax hin und her. zum schluss ist es so, dass man gar nix mehr kapiert.  
            
          also my %hund; vor der schleife anlegen und dann .. muss ich mal rumbasteln.  
            
          `gustl.setTimeOut(2 wochen seychellen);`{:.language-javascript}  
            
          - Gustl 
          
          1. bitte nochmal zum anfang:

            wie ersetze ich in $liste1[0] die 1

            %R1 = ("abc","def","ghi");  
            %R2 = ("cba","fed","ihg");  
              
            my $i = 2;  
              
            if ( $R{$i}[1] eq "fed" ) { do }
            

            "Global symbol "%R" requires explicit package name at.."

            das gleiche problem wie vorher, er sieht $R als eigenständig und nicht als $R1[0].

            • Gustl
            1. Du willst keinen Hash, sondern ein Array of arrays. Matti ist auf den falschen Zug aufgesprungen. Lies perldsc und perllol zum Verständnis.

              my @R = (  
                  [qw(abc def ghi)],  
                  [qw(cba fed ihg)],  
                  [qw(foo bar)],  
                  [qw(quux)],  
              );  
                
              for my $i (0..3) {  
                  print sprintf <<''  
              -----------------------------------------------  
              Wir bearbeiten gerade Element %d des Arrays @R.  
              $R[%d] ist eine Referenz vom Typ %s.  
              Dereferenziert enthält sie %d Elemente.  
              Das erste Element lautet %s, das letzte %s.  
                
                
              , $i, $i, ref($R[$i]), scalar(@{ $R[$i] }), $R[$i][0], $R[$i][-1];  
              };  
                
              __END__  
              -----------------------------------------------  
              Wir bearbeiten gerade Element 0 des Arrays @R.  
              $R[0] ist eine Referenz vom Typ ARRAY.  
              Dereferenziert enthält sie 3 Elemente.  
              Das erste Element lautet abc, das letzte ghi.  
              -----------------------------------------------  
              Wir bearbeiten gerade Element 1 des Arrays @R.  
              $R[1] ist eine Referenz vom Typ ARRAY.  
              Dereferenziert enthält sie 3 Elemente.  
              Das erste Element lautet cba, das letzte ihg.  
              -----------------------------------------------  
              Wir bearbeiten gerade Element 2 des Arrays @R.  
              $R[2] ist eine Referenz vom Typ ARRAY.  
              Dereferenziert enthält sie 2 Elemente.  
              Das erste Element lautet foo, das letzte bar.  
              -----------------------------------------------  
              Wir bearbeiten gerade Element 3 des Arrays @R.  
              $R[3] ist eine Referenz vom Typ ARRAY.  
              Dereferenziert enthält sie 1 Elemente.  
              Das erste Element lautet quux, das letzte quux.  
              
              
              1. Du willst keinen Hash, sondern ein Array of arrays.

                hi cpan, dank dir für deine erklärung. ich weiss was ein array ist, was ein hash ist und auch was mehrdimensionale arrays sind. dem grunde nach jedenfalls.

                ich frage mich nur, muss ich jetzt die komplette struktur meines scripts umbauen, nur weil es nicht möglich scheint die 1 von @array1[0] dynamisch zu ersetzen in form von z.b. @array[$i][0] oder wie auch immer man es vllt. klammern sollte/könnte/müsste. @array1[$i] wird ja auch interpretiert.

                ich habe das selbe script, selbe abfolge, in JS laufen. da klappert alles (mit eval). hab mit eval auch in perl rumgespielt, aber ich brings nicht hin. vernünftige erklärungen auf deutsch find ich auch nicht dazu. im grunde könnte ich eval benutzen. was soll passieren wenn ich nur eine dynamische variable interpretieren lasse und der wert kommt aus einer sql-datenbank, die nur ich beschreibe bzw. ein anderes script das keine eingaben entgegennimmt. aber perls eval sagt bei ($1="wurm" $2="wald") "$1$2" kann nicht als "wurmwald" interpretiert werden. hingegen JS macht aus (var1 wurm var2 wald) mit eval var wurmwald. die synti in JS ist folgende:

                if (eval("ein"+i) == 0) { neu = neu + eval("R"+a+"[0]"); }

                ich brauche eigentlich nur eine perl-syntax für diese eine zeile JS code, und da nur für ein+i und R+a+[0]

                ...........

                vielleicht reden wir alle aneinander vorbei?

                mein script wird ein perl.modul, aber das ist wohl nebensache. ich schicke an eine sub im pm einen string der aus zahlen und doppelpunkten besteht. ich splitte die eingabe bei /:/in ein array (@eingang von mir aus) und lese die anzahl der einzelnen zahlen aus (sagen wir ich sende 5 zahlen). so oft läuft meine erste schleife.

                in der ersten schleife schaut mein script, wie lange die jeweilige zahl ist sagen wir die erste zahl ist 123. wenn die länge der zahl also 3 ist, dann schaut mein script in einen array3, der 10 feste, vierstellige zeichenfolgen hat. ist die zahl 12345 muss das script in array5 kucken. ok soweit?

                in der zweiten schleife, die in schleife 1 läuft, ersetze ich die einzelnen nummern der zahlen in die obigen, 4 stelligen ziffernfolgen. die zweite schleife läuft sooft wie die zahl lang ist, und schaut jedes element an also immer 10 elemente [0] .. [9] (weil jeder array 10 ziffernfolgen enthält und jede einzelne ziffer 0-9 sein kann). ich sage also auf deutsch :-)

                wenn die zahl die länge 3 hat, schaue in array3. ersetze jede ziffer der zahl durch die entsprechende ziffernfolge. also 120 heisst dann

                1 = inhalt element1 aus array3
                2 = inhalt element2 aus array3
                0 = inhalt element0 aus array3

                ist die zahl z.b. 4-stellig (2875 ?) dann

                2 = inhalt element2 aus array4
                ... usw.

                das mache ich von 0-9 in schleife 2, und über die schleife 1 mit jeder zahl aus dem split vom eingansarray.

                am schluss setze ich die ziffernfolgen, die durch zeichenfolgen ersetzt wurden wieder in die ursprüngliche position zwischen doppelpunkte und reurn damit.

                #############

                sagen wir ich übergebe 3 ganzzahlen: 12:9:29

                for my $i (0..2) # 3 zahlen lang
                {
                  @array1 # (10 fixe elemente)
                  @array2 # (10 fixe elemente) ... usw

                die 3 zahlen stehen in $eingang[$i] [0] ... [2] ok?

                erste zahl ist 2-stellig (1 und 2)

                for my $r (0..1) # 2 ziffern lang
                  {

                wenn substr($eingang[$i],$r,1) == 0 und zahl zweistellig dann
                    ersetze 0 in element 0 aus @array2 und hängs einfach
                    an eine neue variable an $neu = $neu.element 0 aus @array2

                ...

                wenn substr($eingang[$i],$r,1) == 9 und zahl zweistellig dann
                    ersetze 9 in element 9 aus @array2 und hängs einfach
                    an eine neue variable an $neu = $neu.element 9 aus @array2

                und das ganze mache ich 10 mal (alle zahlen 0-9
                    = gleichbedeutend mit @array2[elementposition])
                  }

                dann schreib ich hier die einzelnen ergebnisse aus $neu
                   wieder zwischen die doppelpunkte und gibs mit return
                   an mein anderes script zurück.
                }

                mein problem ist es jetzt N U R zu sagen dass bei einer zahl die z.b. 4-stellig ist, er auch bitte in @array4 element x auslesen und an $neu anhängen soll.

                und das wäre: @ array (länge der zahl) [element 4 für die zahl 4 ...]

                $array4[elementnummer]

                =========== $array$r[4] =============

                tja. und das ist das ganze problem das jetzt als dynamische variable zu interpretieren. wie in JS auch.

                muss ich jetzt WIRKLICH wenn ich von münchen nach dachau will (was gleich daneben ist) eine reise von münchen über italien und australien nach dachau machen?

                • Gustl
                1. muss ich jetzt die komplette struktur meines scripts umbauen

                  Ja. In der Zeit, die du gebraucht hast, deine Beschwerde zu schreiben, hättest du das schon dreimal geschafft.

                  Variable Variablennamen sind mit eval möglich, aber ich sage nicht, wie, weil's einfach eine dumme Idee ist. (Lies http://perl.plover.com/varvarname.html ff., um zu verstehen, warum.) Ich bringe aber anderen keine dummen Ideen bei, insbesonders keinen Anfängern.

                  Auch in JavaScript sind variable Variablennamen und eval, so wie du es beschrieben hast, eine dumme Idee. Benutze einfach mehrdimensionale Arrays, das ist die korrekte Datenstruktur!

                  1. ... deine Beschwerde zu schreiben

                    lach, du bist lustig :-) ja, wird wohl ne beschwerde gewesen sein.

                    eval is evil, da hast du recht.

                    frage: wenn mein cgi daten ohne benutzereingaben erzeugt (z.b. randomwerte) und mein modul mit diesen dynamischen evil-variablen nur vergleicht und was neues draus baut, wie kann jemand von aussen hier perl-code ausführen? er müsste dazu doch den code des scripts UND des moduls kennen, oder?

                    muss gestehen, in solchen sachen bin ich wirklich nicht firm. irgendwie kann man alles hacken wenn man will, oder?

                    • Gustl
                    1. irgendwie kann man alles hacken wenn man will

                      Das ist nicht das Problem mit eval, jedenfalls nicht so, wie du es einsetzt. Du hast die Artikelreihe nicht gelesen, die ich im früheren Posting genannt habe. Hole das jetzt nach.

  2. lösung:

    my @R3 = ("hund","katz","maus");  
      
    my $i = 3;  
      
    my $gans = eval"\${R".$i."[1]}";
    

    print"$gans"; gibt "katz" aus

    ich hatte nur $ nicht maskiert. wieso? keine ahnung, in jedem "normalen" string hätt ich es automatisch getan.

    wieso sagt mir das keiner :-)

    das ist meine originalzeile. das war alles.

    if (substr($arr_e[$r],$i,1) == 0) { $neu_e = $neu_e.eval"\${R".$wa_e."_e[0]}"; }

    • Gustl