Newsgroup: it.comp.lang.perl
Titolo: interpolazione variabili

Sperando che esista ancora qualcuno che legge 'sto NG..
 
Il subject è sibillino, ma cerco di chiarirmi :-)
 
Ho la necessità di leggere (e stampare) una frase da un array, che 
contenga una variabile e che detta variabile venga stampata come valore.
 
per capirsi, ho un array '@frasi' con frasi di questo genere:
 
ciao $nome tutto bene?
un saluto a $nome
...
dopo tanto tempo ritorna $nome
ecc. ecc.
 
ma se cerco di stamparle con:
 
my $nome = 'pippo';
my $saluto = $frasi[rand(scalar(@frasi))];
 
ottango le frasi così come le ho sritte sopra e non così:
 
ciao pippo tutto bene?
sarà sicuramente una stronzata, ma non sono riuscito a trovare info in 
merito che non siano i classici 'ciao' . $nome - 'tutto bene?' o "ciao 
$nome tutto bene?".
 
Ah dimenticavo... l'array è su disco e vi accedo con Tie::File, ma 
suppongo che non c'entri niente.
 
grazie a chi potrà darmi una dritta!
 
 
 
 
 
 
 
-- 
Fri(END), Boyfri(END), Girlfri(END), Bestfri(END). Everything has an END 
except...Fam(ILY)! It Has 3 Letters that say I LOVE YOU


 
se ricordo bene (il perl e' un po che non lo uso in modo approfondito) 
quello che fa per te e' eval
 
Es:
  perl -e '$a="bbbb";$b="\$a";print $b,"\n";print eval $b,"\n"'
 
 

  perl -e '$a="bbbb";$b="\$a";print $b,"\n";print eval $b,"\n"'
 
a dire il vero dopo aver postato, ho fatto altri esperimenti ed ho 
provato appnto eval(), ma mi ritornava una stringa vuota... sicuramente 
ho capito male io come usarla, faccio altri esperimenti, grazie!


 ho capito male io come usarla, faccio altri esperimenti, grazie!
 
ho fatto altre prove, al di fuori dell'intero script e sono arrivato 
alla conclusione che sono io a sbagliare qualcosa, almeno spero.. :-D
Infatti queste poche righe funzionano come mi sarei aspettato:
 
my $test;
my $nome = 'pippo';
my @frasi = ("ciao $nome come stai?", "saluti a $nome", "$nome non 
conosce il perl");
print  $frasi[rand(scalar(@frasi))] . "\n";;
print  $frasi[rand(scalar(@frasi))] . "\n";;
print  $frasi[rand(scalar(@frasi))] . "\n";;
 
$test = $frasi[rand(scalar(@frasi))];
print $test . "\n";
$test = $frasi[rand(scalar(@frasi))];
print $test . "\n";
$test = $frasi[rand(scalar(@frasi))];
print $test . "\n";
$test = $frasi[rand(scalar(@frasi))];
print $test . "\n";
 
e ricevo in output:
 
liftman@test:~/test$ perl -w 
eval3.pl
 
saluti a pippo
ciao pippo come stai?
ciao pippo come stai?
saluti a pippo
pippo non conosce il perl
saluti a pippo
ciao pippo come stai?
 
ergo, si tratta al solito di un PEBKAC ed eval() in questo contesto non 
serve ad una fava :-D ingago ancora...
 
vediamo il mio codice originale:
 
my $nome = $1;
tie @frasi, 'Tie::File', 'frasi';
my $mess = "$frasi[rand(scalar(@frasi))]";
untie @frasi;
 
ai miei occhi, pare praticamente lo stesso codice dell'esempio, con 
l'unica differenza dell'uso di Tie::File, quindi riprovo modificando il 
test:
 
#!/usr/bin/env perl
use strict;
use warnings;
use Tie::File;
my @frasi;
my $nome = 'pippo';
tie @frasi, 'Tie::File', 'frasi';
print  $frasi[rand(scalar(@frasi))] . "\n";;
print  $frasi[rand(scalar(@frasi))] . "\n";;
print  $frasi[rand(scalar(@frasi))] . "\n";;
my $test = $frasi[rand(scalar(@frasi))];
print $test . "\n";
  $test = $frasi[rand(scalar(@frasi))];
print $test . "\n";
  $test = $frasi[rand(scalar(@frasi))];
print $test . "\n";
  $test = $frasi[rand(scalar(@frasi))];
print $test . "\n";
untie @frasi
 
e il risultato:
 
liftman@test:~/test$ perl -w 
eval3.pl
 
$nome non conosce il perl
ciao $nome come stai?
ciao $nome come stai?
ciao $nome come stai?
ciao $nome come stai?
ciao $nome come stai?
ciao $nome come stai?
 
a questo punto sono perplesso.. preferivo essere io a sbagliare, 
evidentemente Tie::File, ha un funzionamento anomalo, se proprio non si 
vuol parlare di bug. Forse sono l'unico al mondo che ha bisogno di 
interpolare una variabile all'interno di un array, letto da disco? :-)
 
Alla fine, perdendo "elasticità" nel mio script, posso pure evitare il 
file su disco, e scrivere tutto diretamente, ma vorrei trovare una 
soluzione...



Per forza che qui eval non serve,l'espansione viene gia fatta.
Quando dichiari
 > my $nome = 'pippo';
 > my @frasi = ("ciao $nome come stai?", "saluti a $nome", "$nome non
 > conosce il perl");
 
$nome viene sostituito con il suo valore in quanto la stringa e' 
racchiusa tra doppi quote:
 
my @frasi = ('ciao $nome come stai?', 'saluti a $nome', '$nome non
 > conosce il perl');
 
Cosi l'espansione di $nome non viene fatta


> untie @frasi;
 
ricritto paro paro, senza altro codice:

quindi sono sempre allo stesso punto. Se scrivo l'array nel codice e con 
i doppi apici funziona, altrimenti (pare) di no.
 
questa espressione:
 
my $test = $frasi[rand(scalar(@frasi))];
 
ho provato a "virgolettarla" credo,  in tutti i modi, con e senza eval, 
ma continua a stampare la variabile senza interpolare..
Continuo a sperimentare...


 Continuo a sperimentare...
 
mi sono giocato gli ultimi neuroni ma alla fine ho trovato una soluzione :-)
 
$test = $frasi[rand(scalar(@frasi))];
$test =~ s/\$nome/$nome/;
print $test . "\n";
 
per stavolta sono a posto, grazie comunque per l'aiuto morale .-D



 
Va bene anche con una regex ma anche con una 
$test=eval($frasi[rand(scalar(@frasi))])
 
  perl -e 'my $a="pippo"; print eval($a)' #funziona
 
 
Comunque l'importante e'che hai risolto
 

 Comunque l'importante e'che hai risolto
 
questa è la cosa più importante, l'uso 8o l'abuso...) di eval, lo lascio 
ad un'altra volta :-D


  perl -e 'my $a="pippo"; print eval($a)' #funziona
 
no, non "funziona". sei solo stato fortunato :-)
 
se usassi warning (o ancora meglio strict) vedresti che non stai affatto 
facendo quello che pensi.
 
perl -we 'my $a="pippo"; print eval($a)'
Unquoted string "pippo" may clash with future reserved word at (eval 1) 
line 2.
pippo
 
tu stai valutando pippo come una bareword, che solo fortuitamente 
coincide con la rappresentazione stringa di se stessa. maggiori 
informazioni, se ti servono, le trovi qui:
 
https://perlmaven.com/barewords-in-perl
 
 
ma soprattutto *questo* non funziona:
 
perl -e 'my $a="pippo 1"; print eval($a)'
Number found where operator expected at (eval 1) line 1, near "pippo 1"
	(Do you need to predeclare pippo?)
 
ovvero, stai cercando di eseguire il contenuto di $a come codice. che e' 
una pessima, pessima idea.
 
quello che tu volevi fare e':
 
perl -e 'my $a="pippo"; print eval "qq{$a}";'
 
(il qq{} e' solo piu' leggibile delle virgolette, altrimenti sarebbe 
stato "\"$a\"").
 
le virgolette vanno raddoppiate per dire a Perl di valutare la *stringa* 
(non il codice) contenuta in $a, come se fosse scritta fra virgolette, 
ovvero con interpolazione delle variabili.
 
applicato all'esempio di liftman, questo e' quello che funziona:
 
print eval "qq{$frasi[rand(scalar(@frasi))]\n}";
 
 
cheers,
Aldo


Grazie,ma non  l'ho messo apposta (ne error) perche eval potrebbe dare 
problemi scritto quel modo
Insomma,e voluto



Non sto ad approfondire il codice,e'  comunque meglio la scelta delle 
regex che eval in questo modo.
 

 print eval "qq{$frasi[rand(scalar(@frasi))]\n}";
 
adesso mi è un poco più chiara la faccenda, anche se, visto che 
funziona, lascio la regex :-)
