Newsgroup: it.comp.lang.perl
Titolo: Carattere successivo

Salve,
ho questo problema: devo trovare all'interno di un file di testo (considerato
come un'unica stringa) il carattere che segue immediatamente una data stringa.
Guardando un po' nel manuale ho trovato che applicando la funzione substr()
alla variabile $& oppure $' riesco ad ottenere  cio' che desidero.
Ecco il pezzo di codice in questione:
	$testo = <FILETESTO>;
	while ($testo =~ /$stringa/g)
	{
		$cardopo = substr($',0,1);
Purtroppo questo modo di operare ha il difetto di rallentare notevolmente
l'elaborazione quando il file e' piuttosto grande (> 1M) e le occorrenze della
stringa sono numerose.
Qualcuno puo' suggerire un metodo piu' efficiente di fare cio'?
Grazie in anticipo
Andrea

tento una risposta 
while (<FILETESTO>) {
    s/$stringa(.)/$1/; # $1 recupera ciò che sta nella parentesi, ovvero
                       #   il primo carattere dopo $stringa
    $cardopo= $1;
    }
Però questo funziona solo se la stringa compare una sola volta in una riga
(credo). Non so mica se è più veloce della tua soluzione. prova.
In questo caso il file di testo è scomposto in tante righe (nel tua caso sembra
di no).
 Potresti spezzare il tuo enorme (1 MByte!) $testo con split( $stringa)
in quel caso ogni riga contiene solo una volta $stringa, e il primo carattere di
ogni elemento dell'array che ne risulta è ciò che cerchi tu (salvo per il
primissimo elemento)
@array = split (/$stringa/,join ('',<FILETESTO>) );
unshift(@array);
foreach (@array) {
    $cardopo = substr($_,0,1);
    }
Se la ricerca riguarda solo quella stringa, potresti pure leggere il file e
dirgli di considerare come "a capo" non il carattere \n ma la tua stringa (devi
modificare la variabile $/)
L'unica sfiga consiste nel fatto che il primo carattere, del primo "paragrafo"
in realtà è il primo carattere del file e non quello che segue la tua stringa.
Anche in questo caso non so se è più efficiente (dovrebbe).
Esempio:
$/ = $stringa;
while (<FILETESTO>) {
    $cardopo = substr($_,0,1);


    }
quello che hai scritto cerca una stringa in un
documento, seguita da un carattere (che non sia un
ritorno a capo, in questo caso) e la sostituisce con
il solo carattere, solo una volta.
se la $stringa contiene un ritorno a capo, non
avverra' alcun match.
puoi ovviare il problema con un
while(/$pattern(.)/s) {
	$char=$1;
	......
}
Oha
-- 
"Qualcuno mi spieghi perche' 144 e' l'unico
quadrato perfetto della serie di Fibonacci"

 Qualcuno puo' suggerire un metodo piu' efficiente di fare cio'?
Prima di tutto, se $stringa e' costante nel while, puoi 'bloccare' la RE per
renderla un pelino piu' efficiente
  ($testo =~ /$stringa/go)
Poi devi tenerr conto che $' e $& possono essere inefficienti, specie in
versioni di Perl precedenti alla 5.005. Prima della 5.005, per applicare $'
e $& (e se non erro anche //i), la stringa argomento veniva DUPLICATA almeno
una volta di troppo. Puoi renderti conto di dove possa essere il problema nel 
tuo caso.
Posso suggerirti due strade:
1) non mettere il file in una stringa: mettilo in un array ed esamina le
righe una alla volta. Meno testo da far macinare alle RE.
2) Devi cercare una stringa fissa... allora le RE non servono. Per cercare
  le stringhe si usa index()
 
  $pos = 0;
  $len_s = length $stringa;
  $len_t = length $testo;
  while ($pos < $len_t)
   { my $x;
     $x = index($testo,$stringa,$pos);
     last if $x < 0;
     $cardopo = substr($testo,$x+$len_s,1);
     $pos = $x+$len_s;
   }
  Ho messo un po' di orpelli, ma puoi benissimo sfrondare ed ottimizzare;
  Dovrebbe essere sufficientemente veloce.
 
  Se puoi avere istanze di $stringa che si sovrappongono, devi decidere che
  tipo di risposta ti serve e cambiare l'assegnazione di $pos di conseguenza: 
  quella attuale fa ripartire la ricerca in $cardopo, ma se metti
  $pos = $x+1 inizi semplicemente al carattere successivo e puoi trovare
  istanze parzialmente sovrapposte.
 Maurizio
-- 
Maurizio M. Munafo' / 
mmmu...@netscape.net
"Consider Phlebas, who was once handsome and tall as you" (T.S.Eliot)