Newsgroup: it.comp.lang.perl
Titolo: sostituzione in grassetto.

Ho un problemino. Sto facendo una ricerca all'interno di un testo contenuto
nella variabile $tipo.
$tipo =~ s/$corr/\<B\>$corr\<\/B\>/gi;
questa ricerca fa si che una volta trovata una corrispondenza con $corr
questa venga fatta in grassetto. Funziona bene ma se trovo per esempio:
La casa è bella. Anche il gatto.
e $corr vale "anche" (con la minuscola) la corrispondenza viene verificata
(perchè così voglio), ma la frase viene così sostituita:
La casa è bella. <B>anche</B> il gatto.
e questo non va bene. Come posso fare perchè venga sostiuito in grassetto
l'originale e non il $corr?
Grazie,
Duccio.

 wrote:
: $tipo =~ s/$corr/\<B\>$corr\<\/B\>/gi;
: questa ricerca fa si che una volta trovata una corrispondenza con $corr
: questa venga fatta in grassetto. Funziona bene ma se trovo per esempio:
: La casa è bella. Anche il gatto.
: e $corr vale "anche" (con la minuscola) la corrispondenza viene verificata
: (perchè così voglio), ma la frase viene così sostituita:
: La casa è bella. <B>anche</B> il gatto.
: e questo non va bene. Come posso fare perchè venga sostiuito in grassetto
: l'originale e non il $corr?
#!/usr/bin/perl
$corr = "anche";
$tipo = <DATA>;
# "anche" -> "(a)nche"
$corr = "(" . substr($corr, 0, 1) . ")" . substr($corr, 1);
# Nota le opzioni 'i' case insensitive, 'e' evaluate
# Uno sprintf perche` torna la stringa: print stamperebbe su stdout
# e tornerebbe 1.
# Per ottimizzare puoi mettere substr($corr,3) in una variabile, in modo
# da non dover eseguire sempre il codice e, se e` il caso, usare
# l'opzione 'o' once.
# Alternativamente puoi usare qr// per compilare la RE una sola volta.
$tipo =~ s|$corr|sprintf "<b>$1" . substr($corr,3) . "</b>"|ie;
print "$tipo\n";
__DATA__
La casa è bella. Anche il gatto.
-- 
Nando Santagata: Telemastica & infornatica
Key fingerprint = C2 D9 C0 8E D5 B7 04 97  AF E8 3F 3E AF 4E 7F 9E
finger nando (at) mail (dot) ipers (dot) net   for my PGP public key
Home: 
http://www.ipers.net/~nandos

 La casa è bella. Anche il gatto.
Ma non e' un po' troppo complicato?
 $tipo =~ s|($corr)|<b>$1</b>|gi; 
     #      ^     ^   Tra parentesi per avere $1
 
a me sembra funzionare.
Se fai il match case-insensitive, ma sostituisci con $1 (che e' quello che
hai match-ato) sembra andare sufficientemente bene.
Piuttosto, non dovrebbe fare il semplice match di $corr, perche'
finirebbe per trasformare
 Anche le donne stanche hanno le gonne bianche.
 
in
 <b>Anche</b> le donne st<b>anche</b> hanno le gonne bi<b>anche</b>.
 
e non so se e' quello che vuole :-)
Usando
  $tipo =~ s{\b($corr)\b}{<b>$1</b>}gi;
 
si produce, forse correttamente,
 <b>Anche</b> le donne stanche hanno le gonne bianche.
Maurizio
-- 
Maurizio M. Munafo' / 
mmmu...@netscape.net
"Consider Phlebas, who was once handsome and tall as you" (T.S.Eliot)

il codice di Nando prende in considerazione solo il caso che
la prima lettera sia maiuscola.
se vuoi trovare tutte le combinazioni di maiuscole/minuscole,
questa è una variante più semplice:
    $corr = "anche";
    $tipo = <DATA>;
    $tipo =~ s|(\Q$corr\E)|<B>$1</B>|gi;
    print "$tipo\n";
    __DATA__
    La casa è bella. Anche il gatto. ANCHE le pecore.
HTH.
__END__
# Aldo Calpini
%_ = split undef, join ' ', qw(fahokem
xritajbugne csuctawer jhdtlrnpqloevkshpr
); print map $_{$_}, sort keys %_;

 perl -pe 's/anche/\<B\>$&\<\/B\>/i;'
La casa è bella. <B>Anche</B> il gatto.
Ciao ciao,
Andrea
-- 
"...Unix, MS-DOS, and Windows NT (also known as the Good, the Bad, and 
 the Ugly)."
(by Matt Welsh)

> perl -pe 's/anche/\<B\>$&\<\/B\>/i;'
AAARGHHH!!!! $& e' deprecato!!!! Vade retro!!! :-)
(Scherzo... lo so che $& non fa' piu' cosi' tanto danno in perl 5.005)


 wrote:
: #!/usr/bin/perl
: $corr = "anche";
: $tipo = <DATA>;
: $corr = "(" . substr($corr, 0, 1) . ")" . substr($corr, 1);
: $tipo =~ s|$corr|sprintf "<b>$1" . substr($corr,3) . "</b>"|ie;
: print "$tipo\n";
: __DATA__
: La casa è bella. Anche il gatto.
Carino, ma io avrei fatto fare tutto il lavoro alle RE, cosi`:
#!/usr/bin/perl
$corr = "anche";
$tipo = <DATA>;
$corr = "(" . substr($corr, 0, 1) . ")(" . substr($corr, 1) . ")";
$tipo =~ s|$corr|<b>$1$2</b>|i;
print "$tipo\n";
__DATA__
La casa è bella. Anche il gatto.
E` piu` elegante, piu` corto e piu` comprensibile.
Le performances invece sono circa uguali, infatti testando i casi in cui
la stringa data ha un match o meno si ha:
Benchmark: timing 100000 iterations of dopo_match, dopo_non_match,
prima_match, prima_non_match...
prima_match:  4 wallclock secs ( 4.13 usr +  0.00 sys =  4.13 CPU)
dopo_match:  4 wallclock secs ( 4.08 usr +  0.00 sys =  4.08 CPU)
prima_non_match:  2 wallclock secs ( 1.30 usr +  0.00 sys =  1.30 CPU)
dopo_non_match:  2 wallclock secs ( 1.42 usr +  0.00 sys =  1.42 CPU)





 E` piu` elegante, piu` corto e piu` comprensibile.
Nando... a parte il fatto che ti sei risposto da solo contraddicendoti :),
rimane il problema che cosi' si preserva il case della sola prima lettera.
E poi come fa ad essere piu' comprensibile, almeno rispetto a
 $tipo =~ s|($corr)|<b>$1</b>|gi;
 


>> perl -pe 's/anche/\<B\>$&\<\/B\>/i;'
MMM>AAARGHHH!!!! $& e' deprecato!!!! Vade retro!!! :-)
Perche' ?





 Perche' ?
Lunga storia. Fino a prima di perl 5.005, 
l'uso di $&, $` e $'  era sconsigliato, dal momento che la loro
implementazione era tale da provocare il rallentamento generale di tutto il
proprio programma.
Dettagli su perlfaq6


 wrote:
[ snip ]
MMM>Lunga storia. Fino a prima di perl 5.005, 
MMM>l'uso di $&, $` e $'  era sconsigliato, dal momento che la loro
MMM>implementazione era tale da provocare il rallentamento generale di 
MMM>tutto il proprio programma.
Ah...e' solo quella 'vecchia' storia (e io che pensavo chissa cosa... 8-P)
Pero', se ben ricordo, a rallentare erano le regexp dello stesso programma 
che non usavano $&, $` e $'.
E infatti, se nel programma c'era una sola regexp, usare le parentesi o $& 
era del tutto equivalente.
