SkÃ¥ne Sjælland Linux User Group - http://www.sslug.dk Forside   Tilmelding   Postarkiv   Forum   Kalender   Søg
MhonArc Dato: [Date Prev] [Kronologisk oversigt] [Date Next]   TrÃ¥d: [Date Prev] [Oversigt trÃ¥de] [Date Next]   MhonArc
 

Re: [PERL] perl interpolation i en "" doublequote



Hej Bent,

Jeg har ikke meget tid lige nu, så jeg har ikke studeret dit problem i
detaljer, men det forekommer mig, at du skal læse perlref(1), afsnittet
om symbolske referencer.  Det er kort fortalt hvordan du kommer fra at
have en variabel der indeholder navnet på en anden variabel til at have
værdien af den sidstnævnte.

Hvis vi antager at du har følgene sat på en eller anden måde (evt uden
for din kontrol):

my $www='L1:$r1:$r2';
$link{'L1'} = [ "http://%s/%s"; ];

så forekommer det mig, at du kan opnår det du ønsker ved at bruge noget
som dette:

local ($r1,$r2)=("goda","darvs");

my ($m,@p)=split(/:/,$www);
my $link=$link{$m}->[0];
@p = map { ${ substr($_,1) } } @p;

$link=sprintf($link, @p);
print "$link\n";

Den interessante linie er '@p = map ...'

Den tager alle elementer i @p, fjerner første tegn ('$'), og bruger
resten som en symbolsk reference, der giver værdien af den variabel, der
har det fundne navn.

Skridt for skridt:
	map sætte $_ til elementet dvs '$r1' eller '$r2'
	substr($_,1) fjerner første tegn, så vi har 'r1' eller 'r2'
	${ substr($_,1) } slår dette navns værdi op i symboltabellen

Du har måske bemærket, at jeg har lavet $r1 og $r2 local isf my.  Hvis
de har leksikalt virkefelt, så kan de ikke ses inde i map { }, så de
skal gives dynamisk virkefelt.

Denne måde burde kunne spare dig for en potentielt farlig eval(). Du vil
dog nok stadig have brug for eval, for at fange eventuelle fejl, der kan
opstå, hvis opslaget gennem den symbolske reference ikke lykkes. Det vil
ske, hvis $www indeholder en reference til en variabel, der ikke er
defineret. Brug fx dette for at få mere kontrol over situationen:

@p = map { my $val = eval { ${ substr($_,1) } }; $@ ? undef : $val } @p;

Fejlsituationerne kan ganske givet håndteres bedre end dette.

Jeg håber, at dette kan hjælpe dig.


Og ja, jeg er student fra Søborg Gymnasium, så vi kan meget vel have
mødtes.

bv wrote:
> 
> Hej ssluggere.
> 
> Rene Seindal var meget frisk til at regne ud hvad der foregik sidste
> gang med mit perl reverse spørgsmål. Denne gang er det alvor;
> Det andet var bare nysgerrighed for sjov.
> 
> Man forestiller sig at man har en serie link-macroer som denne:
> $link{'L1'}="http://%s/%s";;
> og man ønsker at indsætte de to '%s'er i form af variabler der
> interpoleres ud fra en angivelse af deres navne i en streng "L1:$r1:$r2".
> Fortolkes som:
> Anvend $link{'L1'} og indsæt $r1 og $r2 som er kendte og definerede.
> 
> Det virker fint når jeg isolerer mekanikken i et lille test program
> som dette. Det kører og giver
> http://goda/darvs
> 
> --8<--
> #!/usr/bin/perl
> $\="\n";
> 
> my ($r1,$r2)=("goda","darvs");
> my $www="L1:$r1:$r2";
> $link{'L1'}="http://%s/%s";;
> 
> ($m,@p)=split(/:/,$www);
> sslug@sslug("\$r1","\$r2");
> sslug@sslug(eval,@p);
> 
> $form=sprintf($link{$m},@p);
> print $form;
> --8<--
> 
> Mit problem er at $r1 og $r2 ikke interpoleres i det rigtige program,
> svarende til at indkoble den første kommentar herover.
> -->@p=("\$r1","\$r2");
> 
> Min klamhuggerløsning bestod i at indkoble den anden kommentar for at
> gennemtvinge interpolationen
> -->@p=map(eval,@p);
> Det er meget ulykkeligt fordi eval interpolerer OG fortolker som en
> perlsætning.
> 
> Det kører egentligt korrekt men giver advarslen
> Warning: Use of "-c" without parens is ambiguous at (eval 19) line 1,
> <STDIN> chunk 347.
> fordi $r1 på et tidspunkt er bla.a 'www.uni-c.dk'
> 
> I det rigtige program er de eneste forskelle at
> 1) $link hentes som første element i en liste
> $link=$link{$m}->[0];
> men det er jo nærmest ligemeget.
> 2) $www bliver læst fra en fil.
> (Vil det svare til at sætte
> $www='L1:$r1:$r2';
> i stedet for
> $www="L1:$r1:$r2";
> ??? Det er hvad jeg tror der sker men hvordan klarer man det?)
> 
> til reference her er koden fra det rigtige program
> 
>  my ($m,@p)=split(/:/,$www);
>  my $link=$link{$m}->[0];
>  $link=sprintf($link,map(eval($_),@p));
> 
> $www blev læst med
> while (<>){
>   next if (/^\#/ or /^\s*$/);
>   /^([A-Z0-9]+)/ && (push(@$1,[split]));
> }
> det er lidt snørklet men et af felterne ender altså i $www.
> 
> /bv
> PS: Til Rene Seinddal: Har vi ikke gået på samme Gymnasium i Søborg?

-- 
René Seindal (sslug@sslug)			http://www.seindal.dk/rene/


 
Forside   Tilmelding   Postarkiv   Oversigt   Kalender   Søg

 
 
Henvendelse vedrørende websiderne til <www_admin>. Senest ændret 2005-08-10, klokken 19:52
Denne side vedligeholdes af MHonArc .