Skip to content.
Script > OperazioniSuTesto > OperazioniSuTesto04Versione

#!/usr/bin/perl
#
# SCRIPT: testo.pl
#
# VERSIONE: 0.4
# DATA: 20/08/2004
#
# AUTORE:
# Vittorio Zuccala' (nathanvi)
# perlmonk@nathanvi.it
#
# LICENZA
# Questo programma è free software; puoi redistribuirlo e/o modificarlo
# nei termini della GNU General Public License come e' stata pubblicata 
# dalla Free Software Foundation dalla versione 2 della Licenza.
# Questo programma e' distribuito nella speranza di essere utile,
# ma SENZA ALCUNA GARANZIA; non si fornisce alcuna garanzia di
# COMMERCIALIZZAZIONE o FUNZIONAMENTO.  Consulta la
# GNU General Public License per maggiori dettagli.
# Originale: http://www.gnu.org/licenses/gpl.txt
# Italiano: http://www.softwarelibero.it/gnudoc/gpl.it.txt
#
# SISTEMA OPERATIVO:
# Scritto su debian linux con scite
# Provato con successo in ambiente windows
#
# OBIETTIVO:
# Mi e' capitato spesso di dover fare delle azioni ripetitive su file, 
# soprattutto di testo e dover scrivere un semplice scriptino per 
# automatizzare l'operazione.
# Spesso, pensando che non avrei piu' dovuto fare la medesima cosa l'ho eseguito
# una volta e poi basta.
# Questo script raccoglie alcune piccole utility per manipolare file di testo e non solo.
# Di seguito sono riportate le operazioni che fa:
# 
# --commenta-- 
# Serve per inserire un carattere di commento "#" o diverso se specificato
#  davanti ad ogni riga di un file.
# Puo' essere molto utile quando, ad esempio si prende del codice di altri e lo si vuole
# eseguire pezzo per pezzo. In questi casi lo si commenta in toto e poi si tolgono
# i commenti solo davanti i pezzi di codice che si vuole eseguire
# 
# --decommenta--
# Fa l'esatto contrario.
# Toglie tutti i commenti davanti alle righe.
# Il carattere di default e' il # ma si puo' modificare con una opzione 
# Per questo motivo, se prima si era utilizzata la funzione commenta si consiglia di 
# non togliere il doppio '#' davanti ai veri commenti perche' sara' tolto il primo comunque.
# 
# --pm2txt--
# Scaricando script dal sito http://www.perlmonks.org, quando le righe sono troppo lunghe,
# va a capo inserendo un + all'inizio della nuova riga
# Questa funzione serve per eliminare questo + e accodare la riga alla precedente
# 
# --fix2csv--
# Serve per convertire un file FDF dove ogni campo e' a lunghezza fissa in uno nel quale 
# ogni campo e' separato da un separatore chiamato anche CSV. 
# Questo puo' essere utile se si hanno software
# aziendali o importazioni (tipicamente da AS/400) in file di tipo fdf ovvero a lunghezza fissa
# e li si vuole importare in programmi come excel, access o, meglio mysql, postgres...
# Il separatore sara' da specificare in linea di comando.
# In questo caso lo script analizza un file "pippo" con campi a lunghezza fissa
# e ne restituisce uno identico con le lettere "bis" davanti del tipo "bis_pippo" con separatore.
# 
# --csv2fix--
# Fa l'esatto contrario del precedente.
# In realta' non mi e' mai capitato di utilizzarlo ma mentre ero in ballo ... :-))
#
# --ricerca--
# Cerca ricursivamente una parola o una stringa, specificata da linea di comando
# nei file contenuti in una directory e nelle directory figlie.
#
# --md5--
# Quando ci passiamo dei file con amici o li scarico da internet, capita di avere a
# disposizione la firma MD5. Questa funzioncina non fa altro che controllare che tale
# firma sia corretta e che, quindi, il file in nostro possesso sia proprio quello che 
# cerchiamo. In caso contrario ci mostra la firma del file che abbiamo. Per questo motivo
# puo' anche essere utilizzato per generare la firma md5 se non si ha a disposizione
# il comando md5sum (come avviene nei sistemi win32). Per fare cio' basta specificare
# una firma nulla dopo aver specificato il file da controllare.
# 
# BACHI:
# Nessun baco riscontrato fino ad ora;
# Si prega contattare l'autore nel caso in cui si scopra qualche baco
#
# DIPENDENZE MODULI:
# Tie::File (Gia' installato di default in ogni distribuzione perl)
# File::Find (Gia' installato di default in ogni distribuzione perl)
# Getopt::Std (Gia' installato di default in ogni distribuzione perl)
# Digest::MD5 (Gia' installato di default in ogni distribuzione perl)
#
# INSTALLAZIONE:
# 1) Cambia la prima riga dello script inserendo il path corretto del tuo
#    interprete perl
#   Es linux: /usr/bin/perl oppure /bin/perl
#   Es windows: c:\perl\bin\perl.exe oppure c:\programmi\perl\bin\perl.exe
#
# 2) Copia lo script in una directory presente nel path
#   Es linux in /usr/bin
#   Es windows in c:\ o c:\windows
#
# UTILIZZO:
# --commenta-- e --decommenta-- e --pm2txt--
# text.pl -c (de)commenta/pm2txt -f files_da_elaborare
# --fix2csv--
# text.pl -c fix2csv -f nome_file -n numero_campi [-s separatore o #] -l lunghezza_campi_in_ordine
# --csv2fix--
# text.pl -c csv2fix -f nome_file -n numero_campi [-s separatore o #]
# --ricerca--
# text.pl -c ricerca -t testo_da_ricercare
# --md5--
# text.pl -c md5 -f file_da_controllare -m firma_md5
# 
#
# ESEMPIO:
# --commenta-- e --decommenta-- e --pm2txt--
# text.pl -c (de)commenta/pm2txt -f "pippo.pl pluto.pl"
# --fix2csv--
# text.pl -c fix2csv -f pippo.txt -n 3 -s ; -l 4 5 6
# --csv2fix--
# text.pl -c csv2fix -f pluto.txt -n 3 -s #
# --ricerca--
# text.pl -c ricerca -t "Andava a casa"
# --md5--
# text.pl -c md5 -f pippo.pl -m firmettina
# 
# 
# INTERPRETE PERL:
# Se hai scaricato questo programma è molto probabile che tu sappia
# cosa sia perl e, probabilmente, hai già un interprete installato sul tuo sistema.
# Se cosi' non fosse, per far funzionare questo script, hai bisogno di
# un altro programma che interpreti i comandi.
# Puoi trovare l'interprete perl su internet e liberamente scaricabile.
#   Linux:   Si utlizzi il tool di installazione pacchetti della propria distribuzione
#   Debian:   apt-get install perl
#   Windows:   http://www.activestate.com/Products/ActivePerl/
#   Altri OS:   http://www.perl.com/CPAN/ports/index.html
#
# INSTALLARE I MODULI AGGIUNTIVI
# Alcuni scipt richiedono l'installazione di moduli aggiuntivi
# In tal caso:
#  In linux:
#   1) aprire una shell e prendere i privilegi di root
#   2) perl -MCPAN -e shell
#   3) install Nome::Modulo
#
#  In windows:
#   1) aprire il prompt dei comandi
#   2) ppm
#   3) install Nome::Modulo
#
# Questo modulo si basa su moduli standard.
# Nessun modulo aggiuntivo e' richiesto.

# Inizializzo i moduli
use strict;
use Tie::File;
use File::Find;
use Getopt::Std;
use Digest::MD5;


# Inizializzo le variabili che servono per le varie funzioni
my @files;
my @argv;
my @dir=('.');
my @estensioni=('.pl','.txt','.php');
my %opt;

#########################################
# Prende le opzioni se ci sono:
# c-->   comando
# f-->   file da elaborare
# h-->   help
# l-->   lista lunghezza campi per fix2csv
# m-->   firma md5
# n-->   numero di campi per il fix2csv
# s-->   separatore di campi per il fix2csv
# t-->   testo da ricercare ricursivamente
getopt('cfhlmnst',\%opt);


#########################################
#Controlla che ci sia una richiesta di help
#oppure se l'utente non ha inserito nessuna
#opzione specifica.
#In tal caso restituisce un help
info_gen() unless(%opt);
info_part() if($opt{h});


#########################################
# Fornisco all'utente l'elenco delle opzioni
# digitate e si da l'opportunita'
# continuare o di fermarsi.

print "Hai inserito le seguenti opzioni.\n\n";
foreach(sort keys(%opt)){
        print "Opzione $_: $opt{$_}\n";
}
print "Premi un tato per continuare o CTRL+C per fermare...\n";
<STDIN>;



####################################
# Se si arriva a questo punto significa che
# l'utente ha inserito delle opzioni che 
# lo soddisfano e vuole continuare l'esecuzione
# dello script

if($opt{c} eq "commenta"){
        controlla_files();
        foreach my $file (@files){
                controlla_esistenza_file($file);
                commenta($file)
        }
}
elsif($opt{c} eq "decommenta"){
        controlla_files();
        foreach my $file (@files){
                controlla_esistenza_file($file);
                decommenta($file)
        }
}
elsif($opt{c} eq "pm2txt"){
        controlla_files();
        foreach my $file (@files){
                controlla_esistenza_file($file);
                pm2txt($file)
        }
}
elsif($opt{c} eq "fix2csv"){
        controlla_files();
        foreach my $file (@files){
                controlla_esistenza_file($file);
                fix2csv($file)
        }
}
elsif($opt{c} eq "csv2fix"){
        controlla_files();
        foreach my $file (@files){
                controlla_esistenza_file($file);
                csv2fix($file)
        }
}
elsif($opt{c} eq "ricerca"){
        ricerca();
}
elsif($opt{c} eq "md5"){
        md5();
}
elsif(!$opt{c}){
        print "Devi inserire un comando!!\n";
        die "'text.pl -h comandi' per una lista\n\n";
}






##########################################################################
##########################################################################
#########      FUNZIONI      ##########################
##########################################################################
##########################################################################


#####################################
#   CONTROLLA FILES

sub controlla_files{
        if($opt{f}){
                @files=split(/ /,$opt{f});
        }
        else{
                print "Mi dispiace ma questo comando richiede uno o piu' files\n";
                print "\tda elaborare. Per fare cio' inerisci l'opzione -f e se\n";
                print "\thai la necessita' di piu' files mettili fra apici\n";
                print "\tEsempio: text.pl -c comando -f \"pippo pluto paperino\"\n";
                die "Rilancia lo script\n";
        }
}

#####################################
#   CONTROLLA ESISTENZA FILE

sub controlla_esistenza_file{
        my $file=shift;
        if(-e $file){
                print "file $file esiste...\n";
        }
        else{
                die "$file non esiste o non riesco ad aprirlo: $!\n";
        }
}


#####################################
#   COMMENTA

sub commenta{
        my $file=shift;
        my @righe;
        tie @righe, 'Tie::File', $file or die "Non riesco ad aprire il file: $!\n";
        print "Lo sto commentando da cima a fondo :-)\n";
        foreach my $riga (@righe){
                $riga='#'.$riga;
        }
        print "Fine commenti...\n\n\n";
        untie @righe;   
}

#####################################
#   DECOMMENTA

sub decommenta{
        my $file=shift;
        my @righe;
        tie @righe, 'Tie::File', $file or die "Non riesco ad aprire il file: $!\n";
        print "Lo sto decommentando da cima a fondo :-)\n";
        foreach my $riga (@righe){
                $riga=~s/^\#(.*)/$1/;
        }
        print "Ho finito di togliere i commenti...\n\n\n";
}


#####################################
#   PM2TXT

sub pm2txt{
        my $file=shift;
        my @righe;
        tie @righe, 'Tie::File', $file or die "Non riesco ad aprire il file: $!\n";
        print "Lo sto convertendo da cima a fondo :-)\n";
        my $i=0;
        my $count=0;
        foreach my $riga (@righe){ 
                #Se inizia la riga con un + lo cancello e accodo la riga alla precedente
                #eliminando quella corrente.
                #Torno in dietro di uno (--$i) per riprendere dalla stesso numero di
                #riga dato ce ho eliminato quella che stavo esaminando.
                if($righe[$i]=~/^\+.*/){
                        ++$count;
                        $righe[$i]=~s/^\+(.*)/$1/;
                        $righe[$i-1]=$righe[$i-1].$righe[$i];
                        splice(@righe,$i,1);
                        --$i;
                }
                ++$i;
        }
        print "Totale righe convertite $count\n";
        print "Fine conversione...\n\n\n";
        untie @righe;
}


#####################################
#   FIX2CSV

sub fix2csv{
        my $file=shift;
        my @righe;
        my $separatore=$opt{s};
        my $num_campi=$opt{n};
        my @lista_campi=split(/ /,$opt{l});
        
        
        if($num_campi && $#lista_campi+1==$num_campi){
                $separatore='#' unless($separatore);
                tie @righe, 'Tie::File', $file or die "Non riesco ad aprire il file: $!\n";
                print "Ho aperto il file $file...\n";
                open TEMP, ">bis_$file" or die "Non posso aprire il file bis dove riversare i dati: $! !!\n\n";
                print "Ho aperto bis_$file dove sto riversando i dati...\n\n";
                foreach my $riga (@righe){
                        my $i=0;
                        my $tot=0;
                        
                        while($lista_campi[$i]){
                                my $valore=substr($riga,$tot,$lista_campi[$i]);
                                $tot+=$lista_campi[$i];
                                
                                $valore=~s/^\s+?//;
                                $valore=~s/\s+?$//;
                                
                                ++$i;   
                                print TEMP $valore,$separatore if($i<$#lista_campi+1);
                                print TEMP $valore if($i==$#lista_campi+1);
                        }
                        print TEMP "\n";
                }
                untie @righe;
                close TEMP;
                print "Ho riversato i dati in bis_$file. Ready to go!\n";
        }
        else{
                print "Devi inserire il numero di campi con l'opzione -n\n";
                print "Segue la lista delle lunghezze dei campi con l'opzione -l\n";
                print "Esempio: -c fix2csv -n 3 -l 3 5 6\n";
                die "Rilancia lo script\n";
        }
}






#####################################
#   CSV2FIX

sub csv2fix{
        my $file=shift;
        my @righe;
        my $separatore=$opt{s};
        my $num_campi=$opt{n};
        
        if($num_campi && $separatore){
                tie @righe, 'Tie::File', $file or die "Non riesco ad aprire il file: $!\n";
                print "Ho aperto il file $file... Controllo la lunghezza dei campi!\n";
                
                #Il primo giro serve per rendersi conto di quanto sono lunghi i campi
                #Li memorizzo in un array @max
                my @temp;
                my @max;
                
                foreach my $riga (@righe){
                        my @temp=split(/$separatore/,$riga);
                        my $i=0;
                        while($temp[$i]){
                                $max[$i]=length($temp[$i]) if length($temp[$i])>$max[$i];
                                $i++;
                        }
                }   
                
                untie @righe;
                
                tie my @righe, 'Tie::File', $file or die "Non riesco ad aprire il file: $!\n";
                open TEMP, ">bis_$file" or die "Non posso aprire il file bis dove riversare i dati: $! !!\n\n";
                print "Ho aperto bis_$file dove sto riversando i dati...\n";
                #Altro giro per elaborare i campi ma questa con la lunghezza fissa
                #nota a priori dal ciclo precedente
                foreach my $riga (@righe){
                        @temp=split(/$separatore/,$riga);
                        my $i=0;
                        while($temp[$i]){
                                printf TEMP ("%-$max[$i]s",$temp[$i]);
                                ++$i;
                        }
                        print TEMP "\n";
                }
                
                close TEMP;
                untie @righe;
                print "\nHo riversato i dati in bis_$file. Ready to go!\n";
                
        }
        else{
                print "ATTENZIONE: Devi inserire il separatore con l'opzione -s\n";
                print "Seguito da il numero di campi con l'opzione -n\n";
                die "Riavvia lo script\n";
        }
}

####################################
############# RICERCA TESTO IN FILE!!

sub ricerca{
        
        my $ricerca=$opt{t};
        die "Devi inserire il testo da ricercare con l'opzione -t\n" unless($ricerca);
        print "\nSto per ricercare la stringa '$ricerca'\n";
        print "nei file con estensione\n";
        foreach(@estensioni){print $_," ";}
        print "\nPremi enter per confermare oppure premi esci e cambia\n";
        print "la variabile \@estensioni nello script!\n";
        <STDIN>;
        
        my @file=find(\&wanted, @dir);
        print "Fine ricerca\n\n";
        
        sub wanted { 
                foreach my $estensione (@estensioni){
                        if(/$estensione/){
                                open FILE, $_ or print "Non sono riuscito ad aprire $_: $!";
                                while(my $riga=<FILE>){
                                        if($riga=~/$ricerca/){
                                                print "Ho trovato la stringa cercata:\n";
                                                print "File: $File::Find::name\n";
                                                print "Stringa:\'$riga\'\n\n";
                                        }
                                }
                        }
                }
        }
        
}


###########################
# MD5 CONTROLLO
sub md5{
        die "Devi inserire la firma trovata md5 per il controllo con opzione -m" unless($opt{m});
        die "Devi inserire un file da controllare con opzione -f" unless($opt{f});
        controlla_esistenza_file($opt{f});
        my $file = $opt{f};
        
        open(FILE, $file) or die "Can't open '$file': $!";
        binmode(FILE);
        
        my $firma=$opt{m};
        
        #Verifico la firma MD5
        my $controllo=Digest::MD5->new->addfile(*FILE)->hexdigest;
        
        #Effettuo il controllo
        if($firma eq $controllo){
                print "OK! Il file e' quello voluto!!\n";
        }
        else{
                print "ATTENZIONE!! Non e' il file che vuoi.\n";
                print "La firma di questo e': $controllo\n";
        }
        
}

########################################
########################################
#   INFORMAZIONI SU
#   HELP
########################################
########################################



########################################
# Informazioni generali
sub info_gen{
        print "Questo programma raccoglie una serie di utility per \n";
        print "la manipolazione di file di testo.\n";
        print "Per la lista dei comandi: text.pl -h comandi\n";
        print "Per info su un comando: text.pl -h nome_comando\n";
        die "Ravvia il programma con la giusta opzione";
}

########################################
# Informazioni su un comando
sub info_part{
        if($opt{h} eq 'comandi'){
                print "Ogni comando si richiama con l'opzione -c\n";
                print "I comandi disponibili sono i seguenti:\n";
                print "commenta: serve per mettere un simbolo di commento\n";
                print "\tdavanti ad ogni riga di un file in modo da poterlo rivederlo da zero\n";
                print "decommenta: fa l'esatto contrario. Toglie davanti ad ogni riga\n";
                print "\til simbolo di commento.\n";
                print "fix2csv: trasforma un file con campi a lunghezza fissa in un CSV\n";
                print "csv2fix: trasforma un CSV in un file con campi a lunghezza fissa\n";
                print "md5: controlla la firma md5 di un file\n";
                print "pm2txt: fissa il bug dell'importazione degli script dal sito di\n";
                print "\tperlmonks nei quali rimane un + all'inizio di alcune righe.\n\n";
                die "Per avere info maggiori su un comando: text.pl -h comando\n";
        }
        elsif($opt{h} eq 'commenta'){
                print "Questa feature e' utile a chi programma e, di tanto in tanto \n";
                print "scarica degli script da internet che vuole riadattare ai propri\n";
                print "scopi. In questi casi puo' essere utile commentare tutto il file\n";
                print "in modo da andare a decommentare solo quello che si vuole ed\n";
                print "analizzare il comportamento del programma con calma.\n";
                print "Utilizzo:\n";
                print "text.pl -c commenta -f file_da_commentare\n\n";
                die "Riavvia lo script con questa opzione se e' cio' che cercavi\n";
        }
        elsif($opt{h} eq 'decommenta'){
                print "Questa feature e' utile a chi programma e, di tanto in tanto \n";
                print "scarica degli script da internet che vuole riadattare ai propri\n";
                print "scopi. In questi casi puo' essere utile commentare tutto il file\n";
                print "in modo da andare a decommentare solo quello che si vuole ed\n";
                print "analizzare il comportamento del programma con calma.\n";
                print "Utilizzo:\n";
                print "text.pl -c decommenta -f file_da_commentare\n\n";
                die "Riavvia lo script con questa opzione se e' cio' che cercavi";
        }
        elsif($opt{h} eq 'fix2csv'){
                print "Questa feature e' utile per coloro che hanno necessita' di \n";
                print "importare/esportare spesso dei dati da/a programmi gestionali.\n";
                print "Alcuni programmi gestiscono file a lunghezza fissa mentre altri\n";
                print "con camppi delimitati da un separatore\n";
                print "Lo script converte da file a lunghezza fissa a csv.\n";
                print "Utilizzo:\n";
                print "text.pl -c fix2csv -f file [-s separatore o #] -n num_campi -l lunghezze_campi\n";
                print "text.pl -c fix2csv -f file -s ; -n 3 -l 8 14 9\n\n";
                die "Riavvia lo script con questa opzione se e' cio' che cercavi\n";
        }
        elsif($opt{h} eq 'csv2fix'){
                print "Questa feature e' utile per coloro che hanno necessita' di \n";
                print "importare/esportare spesso dei dati da/a programmi gestionali.\n";
                print "Alcuni programmi gestiscono file a lunghezza fissa mentre altri\n";
                print "con camppi delimitati da un separatore\n";
                print "Lo script converte da csv a file a lunghezza fissa.\n";
                print "Utilizzo:\n";
                print "text.pl -c csv2fix -f file -n num_campi [-s separatore o #]\n";
                print "text.pl -c csv2fix -f file -n 3 -s #\n\n";
                die "Riavvia lo script con questa opzione se e' cio' che cercavi\n";
        }
        elsif($opt{h} eq 'ricerca'){
                print "Questa feature e' utile a chi vuole ricercare\n";
                print "del testo su piu' files ricorsivamente e scoprire se ci\n";
                print "file che contengono tale testo...\n";
                print "Utilizzo:\n";
                print "text.pl -c ricerca -t testo_da_cercare\n";
                die "Riavvia lo script con questa opzione se e' cio' che cercavi";
        }
        elsif($opt{h} eq 'md5'){
                print "Questa feature soprattutto quando si scaricano o ci passano\n";
                print "tramite internet dei file ed abbiamo la firma md5 per controllare\n";
                print "che il file sia quello in nostro possesso\n";
                print "Utilizzo:\n";
                print "text.pl -c md5 -f file_da_controllare -m firma_md5_del_file\n";
                die "Riavvia lo script con questa opzione se e' cio' che cercavi";
        }
        
        else{
                print "Il comando da te inserito non mi e' noto\n";
                die "Per una lista di comandi: \"text.pl -h comandi\"\n";
        }
        
}

-- VittorioZuccala - 04 Jan 2005


Ultima versione: r1.1 - 06 Jan 2005 - 19:55 - Main.guest
 
Se riconosciuto dal sistema come utente: Main.guest