Newsgroup: it.comp.lang.perl
Titolo: Aiuto per script Perl

Ciao, sono un neofita di Perl, sto cominciando ad usarlo per la tesi.
Devo realizzare uno script che in pratica deve analizzare un file di
testo, che non è altro che una sequenza di circa 1000 comandi linux
(per esempio: sudo, ls, pwd, cd, ssh, ecc....), uno per ogni riga, le
righe sono numerate. Quello che deve fare lo script è contare il
numero di volte che è stato usato ogni comando e calcolare le distanze
(minima, massima e media) tra un comando e ogni altro comando, per
distanza intendo il numero di righe.
Faccio un esempio:
file di testo con i comandi:
7 ls
8 cd
9 sudo
10 ls
11 ls
12 more
13 clear
14 rm
15 ls
16 htmlview
17 htmlview
18 lsof
19 cd
20 ssh
21 sudo
Allora le distanze sono
- ls e cd ---> minima=1 (posizioni 7 e 8),massima=4 (pos. 15 e
19),media=2.5
- ls e sudo --> min=2 (pos 7 e 9), max=6 (pos. 15 e 21), media=4
- ls e ls --> min=1 (pos 10 e 11), max=4 (pos. 11 e 25), media=2.5
- ls e more ....................
ecc..........
non so se avete capito...
avete qualke suggerimento??

 distanza intendo il numero di righe.
1) Apri il file,
2) leggi riga per riga,
3) con una semplice espressione regolare separi il numero dal comando (con 
eventuali parametri se ci sono)
Ti fai un hash in cui:
- per chiave usi il comando
- al valore associ un ulteriore hash con le coppie che ti servono per i 
calcoli (es: ultimo visto=>7, dist_minima=>1, dist_massima=>4, ecc...). 
Questi li puoi calcolare tutti sapendo giusto la riga attuale, l'ultima in 
cui hai visto il comando e il valore attuale del calcolo.

Ho provato a fare come dici tu ma ho dei problemi a inserire i valori
nell' hash, cioè non mi inserisce niente.
Quello che faccio io è scorrere il file riga per riga e tramite il
comando exists controllo se la chiave (il comando cioè), è già
presente nell'hash o meno. Ma come dicevo prima non riesco a
inserire.
Io inserisco in questo modo:
%hash=("$comando" => "1");
In questo esempio voglio inserire come chiave il comando letto e come
valore in questo caso 1 per fare un esempio.
Ogni volta voglio inserire in coda all'hash.
cosa sbaglio? potresti postarmi il codice di come lo faresti tu questo
inserimento?
grazie

 ha scritto:

my $hash;
$hash->{"$comando"} = 1;
Io però farei... (suppondendo solo di calcolare la distanza massima dal 
precedente)
my $hash; # hash dei comandi, sarà un "hash di hash".
per ogni riga... (ti becchi $comando e $rigaattuale che sarà ovviamente un 
semplice contatore)
my $valori = $hash->{"$comando"}; #hash per ogni comando con i valori che ti 
servono.
if ($valori->{"max_distanza"}) {
    $valori->{"max_distanza"} = 
($valori->{"max_distanza"}>$rigaattuale-$valori->{"rigaprecedente"})?$rigaattuale-$valori-> 
{"rigaprecedente"}:$valori->{"max_distanza"}
} else { $valori->{"max_distanza"} = 0; #siamo nella prima riga, non era mai 
stato inizializzato,
}
$valori->{"rigaprecedente"} = $rigattuale;
$hash->{"$comando"} = $valori; #ecco quello che intendevo per "hash di 
hash".
Lo generalizzi un po' per calcolarti la distanza minima e media e direi che 
sei a posto (magari facendo dei controlli se il file è vuoto, se ha una sola 
riga, se un comando c'è una sola volta, ecc...).

 ha scritto:

ok. molto probabilmente proverò questa tua soluzione. volevo un pò
esercitarmi con gli hash, riuscendo a contare il numero di volte che
un comando si ripete, con un semplice hash ke ha come chiavi i comandi
e come valore il numero di volte che compare il comando. E  questo
sono riuscito a farlo, ora però devo considerare il problema delle
distanze e quello ke hai detto tu sembra una buona idea. Ti farò
sapere l'esito o se c'è qualke altro problema. grazie 1000


sto riprendendo ora il codice. Potresti spiegarmi i parole povere cosa
rappresenta un hash di hash?? sarebbe un hash con due kiavi e un
valore?


ho capito cosa intendi per hash di hash. vedo di attuare tale
soluzione.

 soluzione.
Arrivo tardi per la spiegazione ma la faccio lo stesso :-)
E' un concetto abbastanza semplice.
Un hash è un insieme di coppie chiave-valore
Un hash di hash è la stessa cosa in cui nel valore metti un hash quindi è un 
insieme di coppie chiave-hash
Quindi per ogni chiave primaria poi possiamo avere "n" chiavi secondarie 
ciascuna legata al suo valore.

 ha scritto:

sono vicino alla soluzione.  però ho un problema:
il file di testo lo devo leggere dall'alto verso il basso, cioè
dall'ultima riga alla prima.
Ho cercato un pò in giro e l'unica suggerimento che ho trovato è
quello di usare la funzione "reverse", e cioè aprire il file e
associarlo ad un array in questo modo:
@righe=reverse (<FILE> ); #in questo modo ho il file al contrario
all'interno dell'array
ma essendo il file composto da circa 1000 righe, succede che la
memoria va in overflow, quindi non mi resta che tentare un altra
strada.
qualche suggerimento?

strada.
Quanto è grande questo file? "1000 righe" dice veramente poco sulla
quantità di memoria necessaria: se anche si trattasse di righe di qualche
centinaio di caratteri, si arriva ad una dimensione di qualche centinaia di
Kb, che dovrebbe essere ancora perfettamente trattabile, a meno che tu non
usi un computer di 15 anni fa.
Comunque, se è davvero un file enorme, e se è davvero necessario leggerlo
dal fondo, si possono certamente pensare approcci più intelligenti,
rispetto a leggersi tutto il file in un array. Guarda la funzione seek, e
il modulo File::Tail.
Ciao.

, scriveva:

il file è composto da 1000 righe ed ogni riga ha al max 50 caratteri
per un totale di circa 40kb.
Ho provato a fare in quel modo ma si impalla e mi da un errore di
memoria,
sarà perchè nel frattempo uso pure degli hash per memorizzare altre
informazioni.
Appunto io cercavo un modo per scorrere il file dall'alto verso il
basso senza usare un array,
con seek mi posiziono alla fine del file, e poi come faccio a salire
verso su??

verso su??
Poi torni indietro di un tot, quello che pensi possa corrispondere ad un
certo numero di righe medie, e leggi quello che resta fino alla fine del
file; se in quello che hai letto non trovi un sepratore di riga, torni
indietro di un altro tot, leggi, concateni e così via.
Ripeto che ci sono anche moduli per fare questo: File::Tail,
File::ReadBackwards ...
Ciao.

indietro di un altro tot, leggi, concateni e cosě via.
Anche, per un file di quelle dimensioni, puoi tranquillamente leggere in
avanti nel solito, una riga alla volta; quando arrivi alla fine, l'ultima
riga che hai letto... be', č l'ultima riga.
Puoi conservare in una variabile la sola ultima riga, o usare un array per
le ultime 2, 3, n righe.
Ciao.

 Ciao.
ho risolto usando il modulo: File::ReadBackwards
grazie 1000

 Ciao.
