Talvolta le cose sono così semplici che sfuggono. È quello che è successo a me, proprio oggi, dopo aver scritto uno script in bash; pochi secondi prima di salvarlo, è andata via la corrente elettrica e ho perso tutto.
Mi sarebbe bastato andare su Modifica -> Preferenze -> Editor
E poi aggiungere il segno di spunta su salvare automaticamente il file corrente ogni tot minuti. Mah! Vabbe' ;)
Alla Prossima.
lunedì 14 dicembre 2015
giovedì 19 novembre 2015
Sox e la funzione repeat
Salve!
Premessa.
SoX è un'utilità a riga di comando che può convertire vari formati di file audio. Può anche applicare svariati effetti a tali file al momento della conversione. Inoltre SoX può riprodurre e registrare file audio.
Per riprodurre un file audio, anzitutto installiamo tutte le librerie Sox.
$ sudo apt-get install libsox-fmt-all
Ora per riprodurre un brano con la funzionalità repeat si fa così:
$ cd Musica
$ play Cammino_nella_notte.mp3 repeat 2
In tal modo lo stesso brano sarà eseguito per due volte.
Alla prossima.
Premessa.
SoX è un'utilità a riga di comando che può convertire vari formati di file audio. Può anche applicare svariati effetti a tali file al momento della conversione. Inoltre SoX può riprodurre e registrare file audio.
Per riprodurre un file audio, anzitutto installiamo tutte le librerie Sox.
$ sudo apt-get install libsox-fmt-all
Ora per riprodurre un brano con la funzionalità repeat si fa così:
$ cd Musica
$ play Cammino_nella_notte.mp3 repeat 2
In tal modo lo stesso brano sarà eseguito per due volte.
Alla prossima.
Etichette:
Sox
sabato 14 novembre 2015
sabato 31 ottobre 2015
Eliminare i file di una directory contenenti una parola determinata.
Salve!
Supponiamo che in una directory, ad esempio in Documenti, abbia tantissimi file di testo e che voglia eliminare solo quelli che contengono, nel testo e non nel titolo, una determinata parola, come fare? Se si vuole evitare di cercare prima la parola in ciascuno di esso e poi eliminarli, si può usare uno script facile facile. ;)
Ovviamente lo script, prima di eliminare un qualsiasi file, chiede il consenso. Nel mio caso ho eliminato tutti i file nel cui testo compariva la parola Fedora. (non ho niente contro Fedora, eh, è solo un esempio) ;)
Alla prossima!
Supponiamo che in una directory, ad esempio in Documenti, abbia tantissimi file di testo e che voglia eliminare solo quelli che contengono, nel testo e non nel titolo, una determinata parola, come fare? Se si vuole evitare di cercare prima la parola in ciascuno di esso e poi eliminarli, si può usare uno script facile facile. ;)
#!/bin/bash
read -p "Quale parola vuoi cercare? " stringa
for file in $(grep -l $stringa *); do
rm -i $file;
done
exit 0
Ovviamente lo script, prima di eliminare un qualsiasi file, chiede il consenso. Nel mio caso ho eliminato tutti i file nel cui testo compariva la parola Fedora. (non ho niente contro Fedora, eh, è solo un esempio) ;)
Alla prossima!
giovedì 29 ottobre 2015
Creare una copia di backup di un file
Salve!
Prima di modificare un qualsiasi file di configurazione dovrebbe essere necessario farne una copia di backup.
In questo post vi dirò un modo estremamente semplice, ma anche elegante, di creare una copia di backup di un file.
Poniamo il caso che il file da modificare si trovi nella directory Documenti
$ cd Documenti
e che si chiami file.conf
Uno dei modi per creare una copia di backup è il seguente
$ cp file.conf{,.bak}
La semplicità è sempre un dopo, mai un prima.
Alla prossima!
Prima di modificare un qualsiasi file di configurazione dovrebbe essere necessario farne una copia di backup.
In questo post vi dirò un modo estremamente semplice, ma anche elegante, di creare una copia di backup di un file.
Poniamo il caso che il file da modificare si trovi nella directory Documenti
$ cd Documenti
e che si chiami file.conf
Uno dei modi per creare una copia di backup è il seguente
$ cp file.conf{,.bak}
La semplicità è sempre un dopo, mai un prima.
Alla prossima!
Etichette:
Bash,
Brevi esercizi,
cp
mercoledì 28 ottobre 2015
Come tee nessuno!
Salve!
Oggi parliamo, ma solo per un esempio, del comando tee. Per approfondire vi invito ad andare sulla pagina di Wikipedia.
In questo caso l'output del comando "echo" viene passato contemporeaneamente, grazie a tee, a tre comandi diversi, che lo elaborano e ne restituiscono i rispettivi risultati:
1. Il primo sed aggiunge l'underscore.
2. Il secondo sed converte la frase da minuscolo in maiuscolo.
3. Il comando rev inverte i caratteri della frase.
Alla prossima.
Oggi parliamo, ma solo per un esempio, del comando tee. Per approfondire vi invito ad andare sulla pagina di Wikipedia.
$ risultato=$(echo "Come tee nessuno"| tee >(sed 's/ /_/g') >(sed 's/\(.*\)/\U\1/') >(rev))
$ echo "$risultato"
In questo caso l'output del comando "echo" viene passato contemporeaneamente, grazie a tee, a tre comandi diversi, che lo elaborano e ne restituiscono i rispettivi risultati:
1. Il primo sed aggiunge l'underscore.
2. Il secondo sed converte la frase da minuscolo in maiuscolo.
3. Il comando rev inverte i caratteri della frase.
Alla prossima.
Etichette:
Bash,
Brevi esercizi,
Progetto Bash,
Rev,
Sed,
Tee
Sequenza di numeri [bash]
Salve!
Espansione di parentesi graffe VS il comando Seq.
$ echo {1..5} | tr ' ' '\n'
$ seq 1 5
$ echo {1..5}
$ seq -s ' ' 1 5
dove -s sta per output separator.
$ echo {001..5}
$ seq -s " " 001 5
$ echo -e {0..5}"\xc2\xb0"
$ seq -w 0 5 | sed 's/$/\xc2\xb0/' | tr "\n" " "; echo
"\xc2\xb0" = simbolo del grado
Incremento positivo
$ echo {1..10..2}
$ seq -s " " 1 2 10
Incremento negativo
$ echo {10..1..2}
$ seq -s " " 10 -2 1
E poi...
$ echo {a..z}
$ echo {a..z..3}
E ancora
$ echo -e {Lubit,Linux}"\xc2\xae"
\xc2\xae = simbolo del marchio registrato.
Alla prossima!
Espansione di parentesi graffe VS il comando Seq.
$ echo {1..5} | tr ' ' '\n'
$ seq 1 5
$ echo {1..5}
$ seq -s ' ' 1 5
dove -s sta per output separator.
$ echo {001..5}
$ seq -s " " 001 5
$ echo -e {0..5}"\xc2\xb0"
$ seq -w 0 5 | sed 's/$/\xc2\xb0/' | tr "\n" " "; echo
"\xc2\xb0" = simbolo del grado
Incremento positivo
$ echo {1..10..2}
$ seq -s " " 1 2 10
Incremento negativo
$ echo {10..1..2}
$ seq -s " " 10 -2 1
E poi...
$ echo {a..z}
$ echo {a..z..3}
E ancora
$ echo -e {Lubit,Linux}"\xc2\xae"
\xc2\xae = simbolo del marchio registrato.
Alla prossima!
venerdì 23 ottobre 2015
Lubit e internet per tutti!
Dopo un lungo periodo di "riposo" rieccomi qui con un breve, davvero breve, articolo che ritengo possa essere utile.
Probabilmente molti di voi avranno già sperimentato la soluzione che vado a mostrarvi, ma comunque, siccome è tornata utile a me in un periodo di difficoltà, preferisco scrivere due righe per condividerla.
Problema:
mi trovo fuori casa , non ho collegamento internet wifi e dispongo solo di una chiavetta usb per collegare il pc.... ok e se volessi collegare anche il mio smartphone , tablet o un secondo pc utilizzando la stessa connessione??
Lubit ha già tutto quello che ci serve per risolvere il problema!
Parto dal presupposto che sia già stata configurata la connessione tramite chiavetta , fatto questo basterà creare una rete wifi in modo da far diventare il pc un access point.
In pratica si fa così, clicchiamo con tasto sinistro del mouse sul network manager ( l'iconcina in alto a destra che rappresenta il collegamento), selezioniamo "crea nuova rete Wi-Fi", compiliamo il form col nome che vogliamo dare alla nuova rete, il protocollo di sicurezza e la chiave di protezione della rete (naturalmente possiamo anche scegliere nessuna sicurezza per avere una rete aperta) e confermiamo tutto.
A questo punto la rete è stata creata, in alto si nota l'attività di configurazione e avvio della rete, pochi secondi e abbiamo pronta la nuova rete wi-fi quindi possiamo selezionarla sui nostri dispositivi che cosi' avranno accesso alla rete, la stessa che usa il pc collegato direttamente con la chiavetta.
La rete non si avvia automaticamente quindi dopo aver avviato il pc dobbiamo selezionare la rete creata dalla lista delle reti disponibili.
L'ho detto, semplice ma utile! :)
A presto.
Saluti!
Probabilmente molti di voi avranno già sperimentato la soluzione che vado a mostrarvi, ma comunque, siccome è tornata utile a me in un periodo di difficoltà, preferisco scrivere due righe per condividerla.
Problema:
mi trovo fuori casa , non ho collegamento internet wifi e dispongo solo di una chiavetta usb per collegare il pc.... ok e se volessi collegare anche il mio smartphone , tablet o un secondo pc utilizzando la stessa connessione??
Lubit ha già tutto quello che ci serve per risolvere il problema!
Parto dal presupposto che sia già stata configurata la connessione tramite chiavetta , fatto questo basterà creare una rete wifi in modo da far diventare il pc un access point.
In pratica si fa così, clicchiamo con tasto sinistro del mouse sul network manager ( l'iconcina in alto a destra che rappresenta il collegamento), selezioniamo "crea nuova rete Wi-Fi", compiliamo il form col nome che vogliamo dare alla nuova rete, il protocollo di sicurezza e la chiave di protezione della rete (naturalmente possiamo anche scegliere nessuna sicurezza per avere una rete aperta) e confermiamo tutto.
A questo punto la rete è stata creata, in alto si nota l'attività di configurazione e avvio della rete, pochi secondi e abbiamo pronta la nuova rete wi-fi quindi possiamo selezionarla sui nostri dispositivi che cosi' avranno accesso alla rete, la stessa che usa il pc collegato direttamente con la chiavetta.
La rete non si avvia automaticamente quindi dopo aver avviato il pc dobbiamo selezionare la rete creata dalla lista delle reti disponibili.
L'ho detto, semplice ma utile! :)
A presto.
Saluti!
Ricerca case-insensitive e sostituzione con sed.
Salve!
Supponiamo di avere i seguenti dati contenuti nel file prova
luigi Marco luCa
Nino lucA MassImo
Vincenzo Andrea LuCA
Nino LUca Ivo Neo
Luigi LUCA Ivo Rob
Come potete notare il nome Luca è stato scritto in modo non corretto.
Il nostro intento è quello di fare una ricerca case-insensitive e correggere il nome in questione.
Perchè si possa avere la ricerca case-insensitive e la sostituzione in modo globale, si scrive così:
$ sed 's/luca/Luca/Ig' prova
In altri termini, diciamo a sed di sostituire le stringhe luCA, LuCA, LUCa e LUCA con la stringa Luca.
Alla prossima!
Supponiamo di avere i seguenti dati contenuti nel file prova
luigi Marco luCa
Nino lucA MassImo
Vincenzo Andrea LuCA
Nino LUca Ivo Neo
Luigi LUCA Ivo Rob
Come potete notare il nome Luca è stato scritto in modo non corretto.
Il nostro intento è quello di fare una ricerca case-insensitive e correggere il nome in questione.
Perchè si possa avere la ricerca case-insensitive e la sostituzione in modo globale, si scrive così:
$ sed 's/luca/Luca/Ig' prova
In altri termini, diciamo a sed di sostituire le stringhe luCA, LuCA, LUCa e LUCA con la stringa Luca.
Alla prossima!
mercoledì 21 ottobre 2015
Archivio compresso criptato [Brevi Esercizi]
Salve!
Oggi creamo un archivio compresso criptato. In passato abbiamo già parlato di archiviazione e compressione, perciò non mi dilungo sull'argomento.
Per fini pratici e a mo' di esempio, anzitutto mi creo la directory "prova"
$ mkdir prova
ora mi sposto al suo interno
$ cd prova
E all'interno di essa creo nove file.
$ touch file{01..09}.txt
$ ls
Ora creo l'archivio compresso criptato
Cancello i file.txt (operazione non necessaria e, talvolta, anche pericolosa)
$ rm file*
$ ls
Per decriptare e decomprimere l'archivio:
Ovviamente per decriptare servirà la passphrase che abbiamo creato nella fase di criptazione.
Penso meritino un approfondimento sia la GPG che l'algoritmo AES.
Alla prossima.
Oggi creamo un archivio compresso criptato. In passato abbiamo già parlato di archiviazione e compressione, perciò non mi dilungo sull'argomento.
Per fini pratici e a mo' di esempio, anzitutto mi creo la directory "prova"
$ mkdir prova
ora mi sposto al suo interno
$ cd prova
E all'interno di essa creo nove file.
$ touch file{01..09}.txt
$ ls
Ora creo l'archivio compresso criptato
tar czpf - file* | gpg --symmetric --cipher-algo aes256 -o archivio.tar.gz.gpg
Cancello i file.txt (operazione non necessaria e, talvolta, anche pericolosa)
$ rm file*
$ ls
Per decriptare e decomprimere l'archivio:
gpg -d archivio.tar.gz.gpg | tar xzf -
Ovviamente per decriptare servirà la passphrase che abbiamo creato nella fase di criptazione.
Penso meritino un approfondimento sia la GPG che l'algoritmo AES.
Alla prossima.
venerdì 16 ottobre 2015
Myman, il clone di Pac-Man, su Lubit
Myman è un videogioco in modalità testuale ispirato a Pac-Man, il famoso gioco arcade degli anni '80.
Per averlo su lubit:
Per giocare:
$ myman
Pagina del progetto: http://myman.sourceforge.net/
Per averlo su lubit:
$ sudo apt-get install build-essential
$ sudo apt-get install libncurses5-dev groff
$ wget http://downloads.sourceforge.net/project/myman/myman-cvs/myman-cvs-2009-10-30/myman-wip-2009-10-30.tar.gz
$ tar xvfvz myman-wip-2009-10-30.tar.gz
$ cd myman-wip-2009-10-30/
$ ./configure
$ make
$ sudo make install
Per giocare:
$ myman
Pagina del progetto: http://myman.sourceforge.net/
Etichetta 3D [Convert]
Salve!
Anzitutto scarichiamo il font Candice. Una breve digressione, si dice il font o la font? Ho trovato la soluzione definitiva, almeno spero, qui
Ovviamente possiamo usare i font già presenti su lubit. Per avere la lista completa,
$ convert -list font
Posto che abbiamo scaricato il font Candice nella cartella Scaricati,
$ cd Scaricati
Dopo aver scompattato l'archivio zip (tasto dx del mouse e estrai qui), spostiamo il file nella directory /usr/share/fonts/truetype/
$ sudo su
$ mv CANDY.TTF /usr/share/fonts/truetype/
$ exit
Ora bisogna aggiornare la cache dei font
$ fc-cache -f -v
Infine lo script, il cui nome è 3d.sh
Inutile dire che possiamo cambiare qualsiasi parametro come meglio ci aggrada e che tutto è estremamente intuitivo.
Risultato.
Alla prossima!
P.S.1: Chi volesse sbizzarrirsi con imagemagick, vada a questa pagina. Qui
P.S.2: Avete installato Lubit 6?
Anzitutto scarichiamo il font Candice. Una breve digressione, si dice il font o la font? Ho trovato la soluzione definitiva, almeno spero, qui
Ovviamente possiamo usare i font già presenti su lubit. Per avere la lista completa,
$ convert -list font
Posto che abbiamo scaricato il font Candice nella cartella Scaricati,
$ cd Scaricati
Dopo aver scompattato l'archivio zip (tasto dx del mouse e estrai qui), spostiamo il file nella directory /usr/share/fonts/truetype/
$ sudo su
$ mv CANDY.TTF /usr/share/fonts/truetype/
$ exit
Ora bisogna aggiornare la cache dei font
$ fc-cache -f -v
Infine lo script, il cui nome è 3d.sh
#!/bin/bash
convert -size 480x80 xc:black -font Candice-Regular -pointsize 78 \
-fill white -annotate +25+65 'Lubit Linux' \
-shade 140x45 lubit_linux.jpg
exit 0
Inutile dire che possiamo cambiare qualsiasi parametro come meglio ci aggrada e che tutto è estremamente intuitivo.
Risultato.
Alla prossima!
P.S.1: Chi volesse sbizzarrirsi con imagemagick, vada a questa pagina. Qui
P.S.2: Avete installato Lubit 6?
domenica 4 ottobre 2015
Leggi fin dove ti dico io [sed, awk]
Immaginiamo di avere un testo e, individuata una parola, vogliamo che sed o awk legga (e ci restituisca in output) fino a quella parola, compresa o esclusa. O meglio, fino a quella riga in cui è compresa quella parola (sarebbe meglio dire stringa, eh).
Testo di esempio. [Poesia.txt]
La donzelletta vien dalla campagna,
In sul calar del sole,
Col suo fascio dell’erba; e reca in mano
Un mazzolin di rose e di viole,
Onde, siccome suole,
Ornare ella si appresta
Dimani, al dì di festa, il petto e il crine.
Siede con le vicine
Su la scala a filar la vecchierella
Incontro là dove si perde il giorno;
E novellando vien del suo buon tempo,
Quando ai dì della festa ella si ornava,
Ed ancor sana e snella
Solea danzar la sera intra di quei
Ch’ebbe compagni dell’età più bella.
Primo esempio.
Voglio che awk legga fino alla stringa "crine"
$ awk '{print} /crine/ {exit}' Poesia.txt
Per ottenere lo stesso risultato con sed, avremmo dovuto scrivere:
$ sed '/crine/q' Poesia.txt
Secondo esempio.
Voglio che awk legga fino alla stringa "crine", escludendo, però, la riga che la contiene.
$ awk '/crine/ {exit} {print}' Poesia.txt
Per ottenere lo stesso risultato con sed, avremmo dovuto scrivere:
$ sed '/crine/Q' Poesia.txt
Alla prossima!
Testo di esempio. [Poesia.txt]
La donzelletta vien dalla campagna,
In sul calar del sole,
Col suo fascio dell’erba; e reca in mano
Un mazzolin di rose e di viole,
Onde, siccome suole,
Ornare ella si appresta
Dimani, al dì di festa, il petto e il crine.
Siede con le vicine
Su la scala a filar la vecchierella
Incontro là dove si perde il giorno;
E novellando vien del suo buon tempo,
Quando ai dì della festa ella si ornava,
Ed ancor sana e snella
Solea danzar la sera intra di quei
Ch’ebbe compagni dell’età più bella.
Primo esempio.
Voglio che awk legga fino alla stringa "crine"
$ awk '{print} /crine/ {exit}' Poesia.txt
Per ottenere lo stesso risultato con sed, avremmo dovuto scrivere:
$ sed '/crine/q' Poesia.txt
Secondo esempio.
Voglio che awk legga fino alla stringa "crine", escludendo, però, la riga che la contiene.
$ awk '/crine/ {exit} {print}' Poesia.txt
Per ottenere lo stesso risultato con sed, avremmo dovuto scrivere:
$ sed '/crine/Q' Poesia.txt
Alla prossima!
Etichette:
AWK,
Brevi esercizi,
Sed
mercoledì 30 settembre 2015
Manipolazione del testo all'interno delle parentesi graffe #Bash
Salve!
Ora che Lubit è stata rilasciata, di sicuro, salvo imprevisti, sarò più presente sul blog.
Assegno alla variabile "stringa" il titolo di uno dei più famosi film di Lina Wertmüller
Ora voglio che in output le singole parole siano legate tra loro da underscore
Nei prossimi post continueremo a fare esempi sulle parentesi graffe. :)
Ciao!
P.S. Avete scaricato Lubit 6? Qui.
Ora che Lubit è stata rilasciata, di sicuro, salvo imprevisti, sarò più presente sul blog.
Assegno alla variabile "stringa" il titolo di uno dei più famosi film di Lina Wertmüller
stringa="Travolti da un insolito destino nell'azzurro mare d'agosto"
Ora voglio che in output le singole parole siano legate tra loro da underscore
echo ${stringa// /_}
Nei prossimi post continueremo a fare esempi sulle parentesi graffe. :)
Ciao!
P.S. Avete scaricato Lubit 6? Qui.
lunedì 28 settembre 2015
Lubit 6, nome in codice AKI, è online
Salve!
Finalmente ci siamo riusciti a rispettare la tabella di marcia. Lubit 6 presenta tante novità, hot corners, effetto exposè, lubit plasma panel e tante altre cose, tutte da scoprire. ;)
Per tutte le informazioni e per scaricarla, vi rimando al sito ufficiale del LubitProject: Qui.
Alla prossima!
Finalmente ci siamo riusciti a rispettare la tabella di marcia. Lubit 6 presenta tante novità, hot corners, effetto exposè, lubit plasma panel e tante altre cose, tutte da scoprire. ;)
Per tutte le informazioni e per scaricarla, vi rimando al sito ufficiale del LubitProject: Qui.
Alla prossima!
Etichette:
Lubit
sabato 5 settembre 2015
Verso Lubit 6
Nonostante il caldo assurdo di quest'estate, lo sviluppo di Lubit è andato avanti. Si spera tanto che Lubit 6 sia pronta per la fine di settembre.
Oggi vi vogliamo mostrare, molto semplicemente, come anteprima, alcune immagini salienti.
Insieme a Lubit, si sta portando avanti anche lo sviluppo di un browser, il lubit browser minimal, interamente scritto in Python. I betatester confermano un calo di consumo di almeno del 60% rispetto agli altri browser. Sinceramente non so se riusciremo ad includerlo nel parco software di lubit 6.
Ovviamente si stanno aggiornando tutti i pacchetti deb creati per lubit 5 e in più sono state create ex novo altre applicazioni di cui vi diremo prossimamente.
Questi sono solo piccoli accenni, prossimamente scriveremo un post dove faremo luce su tutte le novità di Lubit 6.
A presto!
Oggi vi vogliamo mostrare, molto semplicemente, come anteprima, alcune immagini salienti.
Insieme a Lubit, si sta portando avanti anche lo sviluppo di un browser, il lubit browser minimal, interamente scritto in Python. I betatester confermano un calo di consumo di almeno del 60% rispetto agli altri browser. Sinceramente non so se riusciremo ad includerlo nel parco software di lubit 6.
Nuovo Conky |
Lubit Plasma Panel |
Nuove icone Wbar |
Il nuovo menu di spegnimento |
Lubit Browser |
A presto!
venerdì 14 agosto 2015
Analisi di un testo [AWK]
Salve!
È da un po' che non scrivo sul blog. Purtroppo d'estate è sempre così. E poi considerando l'eccezionalità del caldo di quest'anno non avrei dovuto scrivere almeno fino al quindici settembre. Dai, speriamo che finisca presto e che ritorni prima di subito il freddo.
Intanto vi dico che lo sviluppo di Lubit 6 prosegue. Si spera che esca per la fine di settembre. Prossimamente vi anticiperemo qualcosa.
Vabbe', oggi voglio semplicemente pubblicare un piccolo script in awk che, dandogli in pasto un testo, vi ritorna il numero totale di righe, di parole, di caratteri, di consonanti e il numero totale di ciascuna vocale.
Lo script:
Insomma è tutto estremamente semplice, è stato un modo per rompere il ghiaccio (si fa per dire). E poi, ora che guardo meglio, c'è anche un piccolo errore, scopritelo voi... ;)
Per quanto riguarda il blog, bollono in pentola tante idee e tante novità. Si spera che al più presto si possa iniziare con un corso di Sistema linux, un corso su Sed e tanti esercizi su bash, awk, python, lua e... insomma si prospetta un autunno caldissimo (no aspetta, meglio freddissimo :D)
Alla prossima!
È da un po' che non scrivo sul blog. Purtroppo d'estate è sempre così. E poi considerando l'eccezionalità del caldo di quest'anno non avrei dovuto scrivere almeno fino al quindici settembre. Dai, speriamo che finisca presto e che ritorni prima di subito il freddo.
Intanto vi dico che lo sviluppo di Lubit 6 prosegue. Si spera che esca per la fine di settembre. Prossimamente vi anticiperemo qualcosa.
Vabbe', oggi voglio semplicemente pubblicare un piccolo script in awk che, dandogli in pasto un testo, vi ritorna il numero totale di righe, di parole, di caratteri, di consonanti e il numero totale di ciascuna vocale.
Il testo |
Output |
#!/usr/bin/awk -f
#Bit3Lux
#count.awk
#Numero di ciascuna vocale, numero di righe, numero di parole,
#Numero di caratteri, numero di consonanti.
BEGIN {
print "\n\tREPORT\n"
}
{
Numero_parole += NF
Numero_caratteri += length
A += gsub (/[Aaà]/,"*", $0)
E += gsub (/[EÈeèé]/,"*", $0)
I += gsub (/[Iiì]/,"*", $0)
O += gsub (/[Ooò]/,"*", $0)
U += gsub (/[Uuù]/,"*", $0)
vocali = A+E+I+O+U
}
END {
print "\n\tNumero di righe: " NR
print "\tNumero di parole: " Numero_parole
print "\tNumero di caratteri: " Numero_caratteri
print "\tNumero di consonanti: " Numero_caratteri - vocali
print "\tNumero vocali: " vocali
print "\tVocale a: " A
print "\tVocale e: " E
print "\tVocale i: " I
print "\tVocale o : " O
print "\tVocale u: " U"\n"
}
Insomma è tutto estremamente semplice, è stato un modo per rompere il ghiaccio (si fa per dire). E poi, ora che guardo meglio, c'è anche un piccolo errore, scopritelo voi... ;)
Per quanto riguarda il blog, bollono in pentola tante idee e tante novità. Si spera che al più presto si possa iniziare con un corso di Sistema linux, un corso su Sed e tanti esercizi su bash, awk, python, lua e... insomma si prospetta un autunno caldissimo (no aspetta, meglio freddissimo :D)
Alla prossima!
lunedì 29 giugno 2015
Estrarre indirizzi e-mail da un file di testo [bash]
Salve!
Non so voi, ma se devo scrivere qualsiasi cosa uso sempre l'editor di testo.
Stamattina ho scritto una lettera lunghissima contenente molti indirizzi e-mail.
Allora mi sono chiesto, c'è un modo per estrarre dalla lettera solo gli indirizzi e-mail? E così ho iniziato a cimentarmi con perl, awk, grep, espressioni regolari e altre diavolerie affini. Tutte cose interessanti, intendiamoci, ma sinceramente impresentabili, e poi diventa difficile spiegare quelle cose in un post, considerando anche che in serata è venuto a farmi visita l'anticiclone africano.
Alla fine mi sono riversato su bash, e devo dire che c'è un sistema veramente semplice per compiere l'operazione di cui sopra.
Immaginiamo di voler estrapolare gli indirizzi email dal seguente testo: (scusate per l'esempio, ma la mia fantasia è inversamente proporzionale al caldo)
Lo script, che può essere lanciato semplicemente da riga di comando, è il seguente:
Ecco il risultato:
Alla prossima!
Non so voi, ma se devo scrivere qualsiasi cosa uso sempre l'editor di testo.
Stamattina ho scritto una lettera lunghissima contenente molti indirizzi e-mail.
Allora mi sono chiesto, c'è un modo per estrarre dalla lettera solo gli indirizzi e-mail? E così ho iniziato a cimentarmi con perl, awk, grep, espressioni regolari e altre diavolerie affini. Tutte cose interessanti, intendiamoci, ma sinceramente impresentabili, e poi diventa difficile spiegare quelle cose in un post, considerando anche che in serata è venuto a farmi visita l'anticiclone africano.
Alla fine mi sono riversato su bash, e devo dire che c'è un sistema veramente semplice per compiere l'operazione di cui sopra.
Immaginiamo di voler estrapolare gli indirizzi email dal seguente testo: (scusate per l'esempio, ma la mia fantasia è inversamente proporzionale al caldo)
ciao Luigi, mi scrivi il tuo indirizzo email?
Il mio indirizzo è il seguente bit3lux@gmail.com
Altri indirizzi messi alla ca**o di cane ciao.birra@gmail.com, ciao.ciao@yahoo.it
come.stai_bene@gmail.com ######## lubit_linux-for_ever@forzalinux.com ########
etc.
Lo script, che può essere lanciato semplicemente da riga di comando, è il seguente:
for i in $(cat dati.txt); do echo $i | grep "@"; done
Ecco il risultato:
Alla prossima!
Etichette:
Bash
martedì 16 giugno 2015
Costruiti per rompersi
Poniamo che esista una multinazionale, dal nome Mistoft, che produce software proprietario...
La Mistoft vende pere? No, vende software proprietario. E il software si consuma? Niente affatto, il software può essere definito "immortale". E i clienti della Mistoft sono infiniti? Sono tanti, ma non infiniti. E allora, se il software non si consuma, come accade per le pere, e i clienti non sono infiniti, come fa la Mistoft, dopo aver venduto il suo sistema operativo a tutti i suoi clienti, a fare nuovi profitti? E qui entra in gioco la obsolescenza programmata.
La Mistoft vende pere? No, vende software proprietario. E il software si consuma? Niente affatto, il software può essere definito "immortale". E i clienti della Mistoft sono infiniti? Sono tanti, ma non infiniti. E allora, se il software non si consuma, come accade per le pere, e i clienti non sono infiniti, come fa la Mistoft, dopo aver venduto il suo sistema operativo a tutti i suoi clienti, a fare nuovi profitti? E qui entra in gioco la obsolescenza programmata.
Cos'è la obsolescenza programmata?
È una pratica attraverso cui ti convinco che ciò che hai comprato è già vecchio e ti costringo a comprarne uno nuovo instillandoti falsi bisogni. E quello che compri è quasi sempre identico a ciò che già hai. Quindi butti una cosa nuova per comprarne una identica, ma con il vestitino diverso.
E allora mi viene da pensare: "È difficile spiegare come l'assurdo possa lentamente infiltrarsi nella realtà, fino a sembrare del tutto normale." ¹
¹ Dylan Dog, Albo 7, La zona del crepuscolo, 1987
È una pratica attraverso cui ti convinco che ciò che hai comprato è già vecchio e ti costringo a comprarne uno nuovo instillandoti falsi bisogni. E quello che compri è quasi sempre identico a ciò che già hai. Quindi butti una cosa nuova per comprarne una identica, ma con il vestitino diverso.
E allora mi viene da pensare: "È difficile spiegare come l'assurdo possa lentamente infiltrarsi nella realtà, fino a sembrare del tutto normale." ¹
¹ Dylan Dog, Albo 7, La zona del crepuscolo, 1987
domenica 7 giugno 2015
Lubit, un sistema per tutti !
Che Lubit sia un sistema operativo semplice, stabile e veloce non è un novità per chi segue questo blog, quindi il titolo di questo post deve avere anche un altro significato , anzi diciamo che ha doppio significato.
L'immagine in alto rappresenta chiaramente l'argomento che andrò a trattare in
questo articolo, si tratta di una installazione centralizzata del sistema che
"serve" più client.
Andiamo quindi subito a vedere come Lubit può essere un sistema per tutti.
Cos'è un Terminal Server
Siamo abituati a pensare i servers come web server, file server, print server e così via, adesso invece andremo a realizzare un OS Server o per meglio dire un Terminal Server.
Lo scopo di questa soluzione è utilizzare meglio le risorse e la capacità di calcolo di un PC mettendoli a disposizione di PC datati, anche senza memoria di massa , che faranno da semplici Thin-Client connesi in rete locale.
Per intenderci andremo a realizzare quello che accade con i terminali stupidi collegati a server unix, chi ha qualche annetto se li ricorderà ;)
Il sistema operativo sarà installato solo sul server e ogni client, collegato alla rete LAN, farà il boot da rete e il login come se si operasse direttamente sul Pc server.
Come funziona.
Si parte da una installazione di Lubit su di una macchina che abbia la capacità e le risorse per gestire con tranquillità la multiutenza visto che permetterà di far lavorare più utenti contemporaneamente, tutto il tutorial si basa sulla versione a 32 bit per assicurare il funzionamento anche con i client un pò datati.
Il secondo requisito per realizzare quanto detto è un sistema che permetta ai client di avviarsi prelevando il sistema operativo da remoto, questa funzione si chiama PXE.
Avrete notato che la maggior parte di pc ha la possibilità in fase di boot di scegliere se avviarsi da una memoria locale o da rete, beh questa è proprio la funzione che ci serve.
Il PXE dev'essere installato e configurato sul server, questo si compone di un DHCP server e di un server TFTP (Trivial File Transfer Protocol).
Ricordo velocemente che il DHCP server (Dynamic Host Configuration Protocol), come dice il nome, è un protocollo di rete che permette di gestire le connessioni degli host assegnando ai client che ne fanno richiesta tutti i parametri di rete, per es. indirizzo ip, subnetmask, DNS e altri parametri specifici per il PXE.
In questo caso la prima cosa che fà il DHCP è fornire ai client, oltre ai parametri di rete, l'indirizzo TFTP dove risiedono i files di sistema da caricare.
Il TFTP server è una versione semplificata di FTP che permette di rendere disponibili dei files in rete, non ha necessità di autenticazione.
Quindi avendo installato e configurato questi due componenti abbiamo la possibilità di accettare delle richieste DHCP, riconoscere e fornire tutti i dati ai client per il boot, e inoltre rendiamo disponibile agli stessi client i files di sistema da leggere tramite TFTP.
Oltre a questi due componenti andremo anche a generare i files di sistema per i client.
Dopo aver spiegato, anche se brevemente, come funziona il tutto andiamo alla parte pratica.
Realizziamo il nostro Terminal Server!
Potremmo installare tutte le funzioni che ho descritto prima a mano singolarmente ma esiste una soluzione rapida e semplice per fare tutto in modo quasi automatico, e siccome quel che conta è il risultato andremo spediti per la via più breve.
Per installare tutto quanto in un colpo solo basta digitare da terminale:
fatto questo abbiamo pronti tutti i servizi che ho elencato in precedenza, naturalmente ora non resta che fare un pò di configurazione.
Innanzitutto partiamo dalla configurazione dei parametri di rete.
Abbiamo appena installato un server dhcp nel nostro PC e quindi, cosa molto importante, se il router ha il servizio dhcp attivo è assolutamente necessario disattivarlo!!!
Configuriamo adesso l'interfaccia di rete del server che garantirà il servizio, dobbiamo configurarla con un ip statico a nosto piacimento, l'unica raccomandazine è di utilizzare ip privati.
Per esempio l'indirizzo ip privato per il server che utilizzerò in questo articolo è 192.168.1.3 netmask 255.255.255.0
Editiamo il file che imposta i parametri per le interfacce di rete:
inserendo le seguenti righe
Il router invece ha indirizzo 192.168.1.1 netmask 255.255.255.0 e garantirà l'accesso ad internet per tutti i PC.
A questo punto cominciamo con il creare l'ambiente di sistema che verrà letto dai client, procediamo da terminale digitando:
ora potete prendere un caffè nel frattempo che viene completata l'operazione (ci vorrà un pò, circa 20 minuti), il caffè non è indispensabile per la riuscita quindi potete optare anche per altro ;)
Finito questo passo, è il momento di configurare i servizi.
Cominciamo con il DHCP, il file da modificare si trova in /etc/ltsp ed ha nome dhcpd.conf , quindi da terminale:
(chi preferisce un editor old style testuale può usare nano al posto di leafpad)
ci troviamo adesso nei parametri di configurazione che dobbiamo personalizzare in base alle nostre necessità, in particolar modo dobbiamo modificare gli indirizzi di rete del server e il range degli ip a disposizione.
Riporto qui il file già pronto per configurae il server così da rendere piu' facile la modifica, basta copiare ;)
Lo scopo di questa soluzione è utilizzare meglio le risorse e la capacità di calcolo di un PC mettendoli a disposizione di PC datati, anche senza memoria di massa , che faranno da semplici Thin-Client connesi in rete locale.
Per intenderci andremo a realizzare quello che accade con i terminali stupidi collegati a server unix, chi ha qualche annetto se li ricorderà ;)
Il sistema operativo sarà installato solo sul server e ogni client, collegato alla rete LAN, farà il boot da rete e il login come se si operasse direttamente sul Pc server.
Come funziona.
Si parte da una installazione di Lubit su di una macchina che abbia la capacità e le risorse per gestire con tranquillità la multiutenza visto che permetterà di far lavorare più utenti contemporaneamente, tutto il tutorial si basa sulla versione a 32 bit per assicurare il funzionamento anche con i client un pò datati.
Il secondo requisito per realizzare quanto detto è un sistema che permetta ai client di avviarsi prelevando il sistema operativo da remoto, questa funzione si chiama PXE.
Avrete notato che la maggior parte di pc ha la possibilità in fase di boot di scegliere se avviarsi da una memoria locale o da rete, beh questa è proprio la funzione che ci serve.
Il PXE dev'essere installato e configurato sul server, questo si compone di un DHCP server e di un server TFTP (Trivial File Transfer Protocol).
Ricordo velocemente che il DHCP server (Dynamic Host Configuration Protocol), come dice il nome, è un protocollo di rete che permette di gestire le connessioni degli host assegnando ai client che ne fanno richiesta tutti i parametri di rete, per es. indirizzo ip, subnetmask, DNS e altri parametri specifici per il PXE.
In questo caso la prima cosa che fà il DHCP è fornire ai client, oltre ai parametri di rete, l'indirizzo TFTP dove risiedono i files di sistema da caricare.
Il TFTP server è una versione semplificata di FTP che permette di rendere disponibili dei files in rete, non ha necessità di autenticazione.
Quindi avendo installato e configurato questi due componenti abbiamo la possibilità di accettare delle richieste DHCP, riconoscere e fornire tutti i dati ai client per il boot, e inoltre rendiamo disponibile agli stessi client i files di sistema da leggere tramite TFTP.
Oltre a questi due componenti andremo anche a generare i files di sistema per i client.
Dopo aver spiegato, anche se brevemente, come funziona il tutto andiamo alla parte pratica.
Realizziamo il nostro Terminal Server!
Potremmo installare tutte le funzioni che ho descritto prima a mano singolarmente ma esiste una soluzione rapida e semplice per fare tutto in modo quasi automatico, e siccome quel che conta è il risultato andremo spediti per la via più breve.
Per installare tutto quanto in un colpo solo basta digitare da terminale:
sudo apt-get install ltsp-server-standalone openssh-server
fatto questo abbiamo pronti tutti i servizi che ho elencato in precedenza, naturalmente ora non resta che fare un pò di configurazione.
Innanzitutto partiamo dalla configurazione dei parametri di rete.
Abbiamo appena installato un server dhcp nel nostro PC e quindi, cosa molto importante, se il router ha il servizio dhcp attivo è assolutamente necessario disattivarlo!!!
Configuriamo adesso l'interfaccia di rete del server che garantirà il servizio, dobbiamo configurarla con un ip statico a nosto piacimento, l'unica raccomandazine è di utilizzare ip privati.
Per esempio l'indirizzo ip privato per il server che utilizzerò in questo articolo è 192.168.1.3 netmask 255.255.255.0
Editiamo il file che imposta i parametri per le interfacce di rete:
sudo leafpad /etc/network/interface
inserendo le seguenti righe
auto eth0
iface eth0 inet static
address 192.168.1.3
netmask 255.255.255.0
gateway 192.168.1.1
Il router invece ha indirizzo 192.168.1.1 netmask 255.255.255.0 e garantirà l'accesso ad internet per tutti i PC.
A questo punto cominciamo con il creare l'ambiente di sistema che verrà letto dai client, procediamo da terminale digitando:
sudo ltsp-build-client
ora potete prendere un caffè nel frattempo che viene completata l'operazione (ci vorrà un pò, circa 20 minuti), il caffè non è indispensabile per la riuscita quindi potete optare anche per altro ;)
Finito questo passo, è il momento di configurare i servizi.
Cominciamo con il DHCP, il file da modificare si trova in /etc/ltsp ed ha nome dhcpd.conf , quindi da terminale:
sudo leafpad /etc/ltsp/dhcpd.conf
(chi preferisce un editor old style testuale può usare nano al posto di leafpad)
ci troviamo adesso nei parametri di configurazione che dobbiamo personalizzare in base alle nostre necessità, in particolar modo dobbiamo modificare gli indirizzi di rete del server e il range degli ip a disposizione.
Riporto qui il file già pronto per configurae il server così da rendere piu' facile la modifica, basta copiare ;)
# Default LTSP dhcpd.conf config file.
#
authoritative;
subnet 192.168.1.0 netmask 255.255.255.0 {
range 192.168.1.20 192.168.1.250;
option domain-name "lubit.local";
option domain-name-servers 192.168.1.3;
option broadcast-address 192.168.1.255;
option routers 192.168.1.1;
# next-server 192.168.1.1;
# get-lease-hostnames true;
option subnet-mask 255.255.255.0;
option root-path "/opt/ltsp/i386";
if substring( option vendor-class-identifier, 0, 9 ) = "PXEClient" {
filename "/ltsp/i386/pxelinux.0";
} else {
filename "/ltsp/i386/nbi.img";
}
}
Come si può vedere ho impostato la lan 192.168.1.0 e subnet 255.255.255.0 dell' ip 192.168.1.3 che è l'indirizzo dell'interfaccia del server, impostato il range di ip disponibili dal 20 al 250, ho dato un nome al dominio e specificato il broadcast, il resto potete lasciarlo così com'è.
Specifichiamo che il server dhcp deve stare in ascolto sull'interfaccio eth0 editando il file
sudo leafpad /etc/init.d/isc-dhcp-server
modifichiamo le variabili
DHCPD_CONF=/etc/ltsp/dhcpd.conf
INTERFACES="eth0"
A questo punto aggiorniamo le chiavi ssh:
sudo ltsp-update-sshkeys
generiamo l'immagine del file di sistema che verrà letto dai client
sudo lstp-update-image
e riavviamo il server DHCP:
sudo /etc/init.d/isc-dhcp-server restart
Il gioco è fatto!
Ora da Lubit Control Panel creiamo un utente per ogni client, questo passo non è indispensabile ma è lo scopo di tutto il lavoro che abbiamo fatto fino ad ora :)
Colleghiamo i client alla rete e avviamo il boot da network.
Se il vosto client è davvero vechiotto o molto particolare e non supporta il boot da rete a, link http://rom-o-matic.net/gpxe/gpxe-git/gpxe.git/contrib/rom-o-matic/ potete creare un floppy disk, chiavetta usb o cd per risolvere .
Ok, sicuramente a questo punto vi trovate davanti al login di Ubuntu, tranquilli è solo l'avvio ... il resto è solo Lubit!
E' tutto, buon divertimento, alla prossima.
Saluti!
venerdì 22 maggio 2015
Chi ha ucciso il software libero?
Sul banco degli imputati porto, con mia grande soddisfazione, il metodo induttivo.
Il metodo induttivo è quel processo mentale che attraverso la valutazione dei casi particolari noti tenta di stabilire una legge universale per predire eventi ignoti (e futuri).
Non so se avete mai sentito parlare del tacchino induttivista...
Un tacchino, in un allevamento statunitense, decise di formarsi una visione del mondo scientificamente fondata.
Il tacchino induttivista che riceveva il pasto tutte le mattine alle ore 9.00, trasse la conclusione che ogni mattina, alle ore 9.00, avrebbe ricevuto da mangiare, per tutta la vita, conclusione che si dimostrò falsa solo il giorno della vigilia di Natale, quando, invece di venir nutrito, fu sgozzato.
Morale della favola: una asserzione non è provata definitivamente da milioni di conferme ma può essere rigettata definitivamente per una sola confutazione.
Einstein avrebbe detto che nessuna quantità di esperimenti potrà dimostrare che ho ragione; un unico esperimento potrà dimostrare che ho sbagliato.
Quindi la pretesa del metodo induttivo è praticamente insostenibile. Con esso non si creano leggi universali, ma dogmi. E si finisce per cristallizzare ciò che più di buono abbiamo: Le idee.
Chi ha ucciso il software libero? Le procedure lo hanno ucciso. Le procedure che, a torto, riteniamo infallibili.
Il mondo nel quale viviamo è un mondo che non capiamo ma che sosteniamo, con arroganza, di capire. Un mondo in cui la nostra vita è plasmata da quanto è incerto e altamente dirompente piuttosto che da un corso di eventi semplice, ben pianificato e nella media. In verità, cercando di controllare gli eventi, attraverso la pianificazione, la programmazione ed elaborando strategie per conquistare il mondo, stiamo aumentando i fattori di alta instabilità, rendendoci più fragili. Più si perde tempo a discutere, a parlare del niente, a pianificare migrazioni, a sensibilizzare le coscienze, a studiare come rendere appetibile un sistema operativo open source alla gente, più sprofondiamo nel baratro.
Lo ha ucciso chi lo avrebbe dovuto promuovere. Lo ha ucciso chi di software libero si riempie la bocca.
Fare, adattarsi, essere, invece di prevedere, pianificare, teorizzare. La verità è che qui, sotto sotto, nessuno si vuole sporcare le mani, e allora si perde tempo a sprecare fiato, inutilmente.
Nassim Taleb, famoso epistemologo, in un suo libro, Il cigno nero, racconta la storia immaginaria di una scrittrice e del suo libro pubblicato sul web che viene scoperto da una piccola casa editrice. Questa pubblica il libro, che diventa un bestseller internazionale. La piccola casa editrice si trasforma così in una grande società, e la scrittrice è diventata famosa.
Il mondo è governato dall'improbabile. Noi non siamo nelle condizioni di conoscere il corso degli eventi. È inutile pianificare, aumenteremmo solo i fattori di alta instabilità. Ce lo dimostrano quotidianamente gli economisti, che studiano studiano e studiano, ma la crisi economica si fa sempre più nera, la disoccupazione aumenta e le fabbriche chiudono.
Ma c'è un altro fattore per cui spendere due parole: Gli esperti. La forza conferita a un tecnico o a uno scienziato da un diploma o una laurea ha un effetto dirompente e incontrollabile. Sempre Taleb, in un altro suo libro, L'antifragile, fa presente che i ponti romani costruiti con il sapere pratico (tipico degli imprenditori), sono ancora lì, a testimoniarci la loro superiorità di approccio rispetto al sapere accademico acquisito sui banchi di scuola.
E poi mi viene da pensare alla Salerno-Reggio Calabria... vabbe'.
Anche la globalizzazione, frutto di procedure sofisticate, pace all'anima sua, è fallita, dobbiamo farcene una ragione. Ciò che resta è il lavoro dell'artigiano. Ciò che resta sono i sogni da realizzare partendo dalla propria realtà territoriale e, soprattutto, sporcandosi le mani.
Il 2016 sarà l'anno di Linux? Da che punto guardi il mondo tutto dipende, diceva una nota canzone.
Il metodo induttivo è quel processo mentale che attraverso la valutazione dei casi particolari noti tenta di stabilire una legge universale per predire eventi ignoti (e futuri).
Non so se avete mai sentito parlare del tacchino induttivista...
Un tacchino, in un allevamento statunitense, decise di formarsi una visione del mondo scientificamente fondata.
Il tacchino induttivista che riceveva il pasto tutte le mattine alle ore 9.00, trasse la conclusione che ogni mattina, alle ore 9.00, avrebbe ricevuto da mangiare, per tutta la vita, conclusione che si dimostrò falsa solo il giorno della vigilia di Natale, quando, invece di venir nutrito, fu sgozzato.
Morale della favola: una asserzione non è provata definitivamente da milioni di conferme ma può essere rigettata definitivamente per una sola confutazione.
Einstein avrebbe detto che nessuna quantità di esperimenti potrà dimostrare che ho ragione; un unico esperimento potrà dimostrare che ho sbagliato.
Quindi la pretesa del metodo induttivo è praticamente insostenibile. Con esso non si creano leggi universali, ma dogmi. E si finisce per cristallizzare ciò che più di buono abbiamo: Le idee.
Chi ha ucciso il software libero? Le procedure lo hanno ucciso. Le procedure che, a torto, riteniamo infallibili.
Il mondo nel quale viviamo è un mondo che non capiamo ma che sosteniamo, con arroganza, di capire. Un mondo in cui la nostra vita è plasmata da quanto è incerto e altamente dirompente piuttosto che da un corso di eventi semplice, ben pianificato e nella media. In verità, cercando di controllare gli eventi, attraverso la pianificazione, la programmazione ed elaborando strategie per conquistare il mondo, stiamo aumentando i fattori di alta instabilità, rendendoci più fragili. Più si perde tempo a discutere, a parlare del niente, a pianificare migrazioni, a sensibilizzare le coscienze, a studiare come rendere appetibile un sistema operativo open source alla gente, più sprofondiamo nel baratro.
Lo ha ucciso chi lo avrebbe dovuto promuovere. Lo ha ucciso chi di software libero si riempie la bocca.
Fare, adattarsi, essere, invece di prevedere, pianificare, teorizzare. La verità è che qui, sotto sotto, nessuno si vuole sporcare le mani, e allora si perde tempo a sprecare fiato, inutilmente.
Nassim Taleb, famoso epistemologo, in un suo libro, Il cigno nero, racconta la storia immaginaria di una scrittrice e del suo libro pubblicato sul web che viene scoperto da una piccola casa editrice. Questa pubblica il libro, che diventa un bestseller internazionale. La piccola casa editrice si trasforma così in una grande società, e la scrittrice è diventata famosa.
Il mondo è governato dall'improbabile. Noi non siamo nelle condizioni di conoscere il corso degli eventi. È inutile pianificare, aumenteremmo solo i fattori di alta instabilità. Ce lo dimostrano quotidianamente gli economisti, che studiano studiano e studiano, ma la crisi economica si fa sempre più nera, la disoccupazione aumenta e le fabbriche chiudono.
Ma c'è un altro fattore per cui spendere due parole: Gli esperti. La forza conferita a un tecnico o a uno scienziato da un diploma o una laurea ha un effetto dirompente e incontrollabile. Sempre Taleb, in un altro suo libro, L'antifragile, fa presente che i ponti romani costruiti con il sapere pratico (tipico degli imprenditori), sono ancora lì, a testimoniarci la loro superiorità di approccio rispetto al sapere accademico acquisito sui banchi di scuola.
E poi mi viene da pensare alla Salerno-Reggio Calabria... vabbe'.
Anche la globalizzazione, frutto di procedure sofisticate, pace all'anima sua, è fallita, dobbiamo farcene una ragione. Ciò che resta è il lavoro dell'artigiano. Ciò che resta sono i sogni da realizzare partendo dalla propria realtà territoriale e, soprattutto, sporcandosi le mani.
Il 2016 sarà l'anno di Linux? Da che punto guardi il mondo tutto dipende, diceva una nota canzone.
mercoledì 20 maggio 2015
Software libero, ma di cosa stiamo parlando?
Il solipsismo è la credenza secondo cui tutto quello che l'individuo percepisce viene creato dalla propria coscienza. Di conseguenza, tutte le azioni e tutto quello che fa l'individuo è parte di una morale prestabilita dal proprio io. L'io che crea il mondo. E questo avviene in maniera trasversale, nel senso che si prescinde da classi e ceti sociali.
L'individuo, nell'accezione peggiore del termine, diviene il centro dell'universo. O, forse, più che di individuo dovremmo parlare dell'ego. Di una sorta di patologia grave dell'io. Un egocentrismo malato e subdolo, schizofrenico e dirompente.
Siamo tutti figli di Cartesio. Per Cartesio, nell'atto in cui io penso, non posso dubitare del fatto che "io esisto". Stabilito questo però risultava difficile, se non impossibile, per Cartesio, determinare qualche conoscenza certa che andasse al di là del Cogito, dell'io penso. Quindi l'unica realtà è l'io che pensa. Cogito, dunque sono.
Siamo nell'ambito dell'autoreferenzialità patologica dell'io. Io, io e solo io. Fateci caso quando parlate con qualcuno, provate a contare quante volte pronunciate il pronome personale "io" in dieci minuti di conversazione.
E siccome l'io è l'unica realtà esistente, tutto il resto diviene un prolugamento di me stesso: Figli, amici, coniuge, gli altri.
Questa è la vera malattia di cui è affetto l'occidente. Ogni cosa altro non è che il prolungamento del proprio io malato. Allora posso decidere di privatizzare l'acqua, posso decidere di destabilizzare politicamente interi popoli per poterli poi meglio depauperare, spogliarli delle proprie ricchezze. Alla fine non faccio male a nessuno, se non a me stesso essendo ogni cosa un prolugamento del mio io. Mi posso permettere di considerare finanche i miei figli come parte di me stesso. Figli mai svezzati e cordoni ombelicali ancora da recidere.
Inquinare, rubare, arroganza, tracotanza non vengono sentiti come immorali, come comportamenti inopportuni. Questo perchè ciò che è giusto e ciò che è ingiusto è stabilito dall'io malato. E siccome gli altri non esistono se non li penso, sono miei prodotti, da usare e gettare come e quando voglio.
In questo contesto parlare di software libero è quasi assurdo. Il software libero pressuppone una base comunitaria. E questa idea, anche a livello inconscio, va a cozzare con le categorie mentali impregnate di solipsismo.
Provate ad osservare un fenomeno. Se si cerca di creare una comunità intorno ad un'idea, in realtà non si crea una comunità, ma un'arena dove i vari "io" lottano per la supremazia. E questo accade perchè ognuno vede gli altri come il prolungamento del proprio io. Ed è guerra senza esclusione di colpi.
L'idea comunitaria del software libero è solo apparente. Assistiamo a progetti impermeabili e portati avanti da poche persone. Tutti, o quasi, rilasciano la ricetta, ma nessuno, o quasi, ti dice la procedura per far interagire i vari elementi e arrivare al dolce. Perchè dire agli altri come si fa se gli altri altro non sono che il prolungamento di me stesso?
Ma anche nel momento in cui rendi aperto un progetto, nel senso che permetti ad altri di imbarcarsi, primo o poi ti accorgi che la gente non viene per aiutarti ma per sovvertire il progetto stesso. Non si tratta di mettersi a disposizione per migliorare un qualcosa, ma ancora una volta si innesca la guerra spietata di supremazia. Ancora una volta è una guerra per la supremazia del proprio io.
Stando così le cose, non dobbiamo lamentarci se il software proprietario prenderà sempre più piede. Anche qui sembrerebbe semplice capire il perchè. Perchè nelle società commerciali, nelle multinazionali non vige una base comunitaria, nell'accezione genuina del termine, ma una reductio ad unum. In altri termini, in queste realtà c'è un capo. E tutti gli altri subalterni. Per contratto si accetta di essere il prolungamento del capo.
"La comunità anzitutto non ha una base contrattuale: essa fiorisce «da germi dati, quando le condizioni sono favorevoli; al suo interno si forma una gerarchia naturale basata sulle differenze di età, forza e saggezza, ma domina un atteggiamento di benevolenza e rispetto reciproci." [Tönnies, sociologo.]
Software libero, ma di cosa stiamo parlando? Intelligenti pauca, ovverosia alle persone intelligenti poche parole...
L'individuo, nell'accezione peggiore del termine, diviene il centro dell'universo. O, forse, più che di individuo dovremmo parlare dell'ego. Di una sorta di patologia grave dell'io. Un egocentrismo malato e subdolo, schizofrenico e dirompente.
Siamo tutti figli di Cartesio. Per Cartesio, nell'atto in cui io penso, non posso dubitare del fatto che "io esisto". Stabilito questo però risultava difficile, se non impossibile, per Cartesio, determinare qualche conoscenza certa che andasse al di là del Cogito, dell'io penso. Quindi l'unica realtà è l'io che pensa. Cogito, dunque sono.
Siamo nell'ambito dell'autoreferenzialità patologica dell'io. Io, io e solo io. Fateci caso quando parlate con qualcuno, provate a contare quante volte pronunciate il pronome personale "io" in dieci minuti di conversazione.
E siccome l'io è l'unica realtà esistente, tutto il resto diviene un prolugamento di me stesso: Figli, amici, coniuge, gli altri.
Questa è la vera malattia di cui è affetto l'occidente. Ogni cosa altro non è che il prolungamento del proprio io malato. Allora posso decidere di privatizzare l'acqua, posso decidere di destabilizzare politicamente interi popoli per poterli poi meglio depauperare, spogliarli delle proprie ricchezze. Alla fine non faccio male a nessuno, se non a me stesso essendo ogni cosa un prolugamento del mio io. Mi posso permettere di considerare finanche i miei figli come parte di me stesso. Figli mai svezzati e cordoni ombelicali ancora da recidere.
Inquinare, rubare, arroganza, tracotanza non vengono sentiti come immorali, come comportamenti inopportuni. Questo perchè ciò che è giusto e ciò che è ingiusto è stabilito dall'io malato. E siccome gli altri non esistono se non li penso, sono miei prodotti, da usare e gettare come e quando voglio.
In questo contesto parlare di software libero è quasi assurdo. Il software libero pressuppone una base comunitaria. E questa idea, anche a livello inconscio, va a cozzare con le categorie mentali impregnate di solipsismo.
Provate ad osservare un fenomeno. Se si cerca di creare una comunità intorno ad un'idea, in realtà non si crea una comunità, ma un'arena dove i vari "io" lottano per la supremazia. E questo accade perchè ognuno vede gli altri come il prolungamento del proprio io. Ed è guerra senza esclusione di colpi.
L'idea comunitaria del software libero è solo apparente. Assistiamo a progetti impermeabili e portati avanti da poche persone. Tutti, o quasi, rilasciano la ricetta, ma nessuno, o quasi, ti dice la procedura per far interagire i vari elementi e arrivare al dolce. Perchè dire agli altri come si fa se gli altri altro non sono che il prolungamento di me stesso?
Ma anche nel momento in cui rendi aperto un progetto, nel senso che permetti ad altri di imbarcarsi, primo o poi ti accorgi che la gente non viene per aiutarti ma per sovvertire il progetto stesso. Non si tratta di mettersi a disposizione per migliorare un qualcosa, ma ancora una volta si innesca la guerra spietata di supremazia. Ancora una volta è una guerra per la supremazia del proprio io.
Stando così le cose, non dobbiamo lamentarci se il software proprietario prenderà sempre più piede. Anche qui sembrerebbe semplice capire il perchè. Perchè nelle società commerciali, nelle multinazionali non vige una base comunitaria, nell'accezione genuina del termine, ma una reductio ad unum. In altri termini, in queste realtà c'è un capo. E tutti gli altri subalterni. Per contratto si accetta di essere il prolungamento del capo.
"La comunità anzitutto non ha una base contrattuale: essa fiorisce «da germi dati, quando le condizioni sono favorevoli; al suo interno si forma una gerarchia naturale basata sulle differenze di età, forza e saggezza, ma domina un atteggiamento di benevolenza e rispetto reciproci." [Tönnies, sociologo.]
Software libero, ma di cosa stiamo parlando? Intelligenti pauca, ovverosia alle persone intelligenti poche parole...
sabato 16 maggio 2015
Un semplice esperimento di Intelligenza Artificiale
Salve!
Non so se ricordate i vecchi film di fantascienza, quelli dove il ragazzo smanettone di turno inizia a dialogare attraverso il pc con una presenza sconosciuta.
Ecco, grazie a Python ho cercato di rivivere quelle atmosfere creando un programmino che, come un bambino, è capace di apprendere e ricordare. In pratica, il programma chiede ciò che non sa e non lo dimentica più.
Presto, una volta sistemato meglio, pubblicherò anche il codice. :)
A presto!
Non so se ricordate i vecchi film di fantascienza, quelli dove il ragazzo smanettone di turno inizia a dialogare attraverso il pc con una presenza sconosciuta.
Ecco, grazie a Python ho cercato di rivivere quelle atmosfere creando un programmino che, come un bambino, è capace di apprendere e ricordare. In pratica, il programma chiede ciò che non sa e non lo dimentica più.
Presto, una volta sistemato meglio, pubblicherò anche il codice. :)
A presto!
sabato 9 maggio 2015
Restiamo in contatto grazie a python [Brevi esercizi]
Salve a tutti,
in questo articolo riporto un piccolo script in python nato per la necessità che ho avuto di restare "in contatto" con un pc collegato ad internet con un ip pubblico dinamico.
Cosa fà lo script?
Molto semplicemente lanciandolo inizia il suo lavoro che consiste in un loop infinito, lavorerà fin quando non lo fermeremo manualmente, e controllerà l'ip pubblico per rilevare variazioni. Se viene rilevato un cambiamento ci invierà una email comunicandoci il nuovo indirizzo.
Ma andiamo a vedere il codice e poi un breve commento.
A seguire abbiamo le variabili con i dati dell' account del mittente e del destinatario delle email di segnalazione, compresi i parametri per l'autenticazione.
Come avrete notato in questo esempio ho usato degli indirizzi gmail, ho fatto questa scelta perchè credo che siano tra i piu' usati ..... vabe' c'è anche da dire che era quello che serviva a me ;)
Cmq il tutto è , come sempre, facilmente personalizzabile.
Le altre variabili sono solo di servizio e quindi non hanno bisogno di ulteriori spiegazioni.
A questo punto inizia il loop che controlla l'ip leggendo il risultato del sito http://ipecho.net/plain che ci fornisce il nostro ip pubblico, lo memorizza e lo confronta con l'ultimo letto.
A questo punto se i due valori non coincidono vuol dire che il nostro indirizzo ip è cambiato e quindi parte il messaggio email che contiene il nuovo ip.
Questo e' quanto, piccolo script ma spero utile anche a voi.
Saluti!
in questo articolo riporto un piccolo script in python nato per la necessità che ho avuto di restare "in contatto" con un pc collegato ad internet con un ip pubblico dinamico.
Cosa fà lo script?
Molto semplicemente lanciandolo inizia il suo lavoro che consiste in un loop infinito, lavorerà fin quando non lo fermeremo manualmente, e controllerà l'ip pubblico per rilevare variazioni. Se viene rilevato un cambiamento ci invierà una email comunicandoci il nuovo indirizzo.
Ma andiamo a vedere il codice e poi un breve commento.
#!/usr/bin/python
# -*- coding: utf-8 -*-
import urllib,smtplib,time
# Tempo di attesa in secondi tra due controlli
attesa = 600
# Parametri per invio email
destinatario = "email_destinataio@gmail.com"
mittente = 'email_mittente@gmail.com'
username = 'email_mittente@gmail.com'
password = 'password'
# Altre variabili
MemoriaIp=""
conta = 0
while True:
conta += 1
print "Controllo n. %i" % conta
# Legge IP pubblico
sock = urllib.urlopen("http://ipecho.net/plain")
ReadIP = sock.read()
sock.close()
if ReadIP != MemoriaIp:
# Comunica nuovo IP a video
print "Rilevato nuovo IP %s" % ReadIP
# Ricorda IP per verifica cambiamento
MemoriaIp = ReadIP
# Prepara variabili per email
oggetto = 'Notifica IP %s' % ReadIP
testo = 'Il tuo IP: %s' % ReadIP
header = 'From: %s\n' % mittente
header += 'To: %s\n' % destinatario
header += 'Subject: %s\n\n' % oggetto
msg = header + testo
#Invia email
server = smtplib.SMTP_SSL("smtp.gmail.com", 465)
server.ehlo()
server.login(username,password)
server.sendmail(mittente, destinatario, msg)
server.quit()
time.sleep(attesa)
Nella parte iniziale troviamo le variabili generali, in particolare attesa è l'intervallo di tempo che passa tra due controlli, il valore è espresso in secondi quindi il valore 600 equivale a 10 minuti.A seguire abbiamo le variabili con i dati dell' account del mittente e del destinatario delle email di segnalazione, compresi i parametri per l'autenticazione.
Come avrete notato in questo esempio ho usato degli indirizzi gmail, ho fatto questa scelta perchè credo che siano tra i piu' usati ..... vabe' c'è anche da dire che era quello che serviva a me ;)
Cmq il tutto è , come sempre, facilmente personalizzabile.
Le altre variabili sono solo di servizio e quindi non hanno bisogno di ulteriori spiegazioni.
A questo punto inizia il loop che controlla l'ip leggendo il risultato del sito http://ipecho.net/plain che ci fornisce il nostro ip pubblico, lo memorizza e lo confronta con l'ultimo letto.
A questo punto se i due valori non coincidono vuol dire che il nostro indirizzo ip è cambiato e quindi parte il messaggio email che contiene il nuovo ip.
Questo e' quanto, piccolo script ma spero utile anche a voi.
Saluti!
Etichette:
Brevi esercizi,
Python
venerdì 8 maggio 2015
Corso Lua - puntata 10 - Applicazioni
Un po' di ripasso
Negli esempi della puntata ci servirà rinfrescarci la memoria su una particolarità di Lua: si possono omettere le parentesi tonde nella sintassi della chiamata a funzione quando viene passato un unico argomento di tipo stringa o di tipo tabella.Pertanto un codice come questo viene interpretato come la richiesta di esecuzione della funzione 'book' con argomento la tabella definita esplicitamente con il costruttore:
book{
author = "Luo Shan Minh",
title = "Great planet"
pages = 123.00 * 1.10, -- :-)
editor = "Father & Sons",
}
Dal punto di vista dell'utente invece, una serie di elementi 'book' di questo tipo salvati in un file di testo rappresentano una sorta di database bibliografico.
Comunque sia i dati così descritti corrispondono a codice Lua perfettamente lecito pronto per essere letto ed eseguito dall'interprete con la funzione predefinita 'dofile()'.
Lua può quindi essere un formato per descrivere i dati ed elaborarli definendo opportunamente funzioni --- nell'esempio la funzione 'book()' --- senza che sia necessario effettuare il parsing che sarebbe invece necessario se i dati fossero per esempio nel formato JSON.
L'inventario
Moltissimi esercizi commerciali alla fine dell'anno redigono l'inventario del magazzino, l'elenco della merce con le quantità rilevate e il costo di acquisto dal fornitore.Il formato dei dati d'inventario
Prevediamo che il record di un articolo sia il seguente:- codice: identificativo univoco articolo;
- descrizione: breve testo descrittivo;
- classe: codice del tipo di articolo;
- fornitore: codice univoco del fornitore;
- reparto: codice univoco del reparto;
- costo: costo di acquisto di un pezzo;
- quantità: pezzi rilevati a magazzino.
Caliamo direttamente questa struttura nel formato auto-descrittivo di Lua:
item{code="C123",
descr="NOME MODELLO",
class = "Sciarpa",
supplier="MYSUP",
department="MYDEP",
cost=123.45,
qty=1,
}
Per eseguire il codice è necessario un file dati di esempio. Scaricatelo da questo link. Nel file già dotato di estensione '.lua' i dati sono casuali rispetto a un insieme limitato di liste. Di seguito vi riporto le prime sei righe nel formato key=value con le parole chiavi che sono sempre le stesse --- spazi, tabulazioni ritorni a capo tra i campi sono liberi:
item{code="546556", descr="546556 - Puzzle", class="Puzzle", supplier="Vivo", department="ARTE",cost=5.00, qty=29,}
item{code="815720", descr="815720 - Forbici", class="Forbici", supplier="Multi", department="SCU", cost=11.00,qty=26,}
item{code="067225", descr="67225 - Diario", class="Diario", supplier="Lifestar",department="CAR", cost=12.00,qty=12,}
item{code="034371", descr="34371 - Cucitrice", class="Cucitrice", supplier="Vartech", department="TEC", cost=6.00, qty=70,}
item{code="070835", descr="70835 - Pennarello",class="Pennarello",supplier="Vivo", department="COL", cost=12.00,qty=69,}
item{code="343307", descr="343307 - Buste", class="Buste", supplier="MySheet", department="CAR", cost=7.00, qty=67,}
...
Come è evidente nell'esempio, i valori testuali sono racchiusi tra doppi apici mentre i valori numerici sono rappresentati con il punto decimale (non possiamo usare la virgola, simbolo già previsto dalla sintassi per la separazione dei campi (a proposito l'ultima virgola è opzionale perché in generale è più semplice aggiungere campi alla tabella)).
Cominciamo con lo scrivere il programma che conti gli articoli in inventario e che accerti o meno che il codice degli articoli per ciascuna riga è effettivamente univoco. Ammetteremo che il file 'dati.lua' si trovi nella stessa directory degli script Lua.
Fatelo per esercizio e poi proseguite nella lettura perciò inserisco un segnalibro in modo che possiate riprendere la lettura dopo aver compiuto l'esercizio.
--- Segnalibro esercizio 1 ---
Ecco come contare gli articoli:
-- codice errato
local i = 0
local function item(t) -- funzione locale?
i = i + 1
end
dofile "dati.lua" -- esecuzione file Lua
print(i)
Per prima cosa osservo che la funzione non può essere locale, e infatti il compilatore Lua ci avverte con "lua: dati.lua:1: attempt to call global 'item' (a nil value)". Quando Lua esegue il file esterno si trova in un secondo chunk in cui non sono visibili le variabili locali al primo pertanto solo la funzione di elaborazione dovrà essere globale.
La seconda osservazione è questa: la funzione 'item()' deve far ricorso a una variabile esterna tramite closure, necessariamente. Infatti può ogni volta avere il solo argomento della tabella del record dell'articolo. Non possiamo poi contare sulla restituzione di un parametro che andrebbe perso quando Lua valuta le espressioni delle chiamate a funzione nel file dati.
Per accertare l'univocità del codice possiamo usare una tabella in cui memorizzare i codici stessi fermandoci se il prossimo codice da includere come chiave è già presente. Il valore può essere un tipo qualsiasi e nell'esempio ho inserito il valore booleano 'true':
local dati = {}
function item(t)
i = i + 1
if dati[t.code] then
error(t.code.." errore riga "..i)
else
dati[t.code] = true
end
end
dofile "dati.lua"
print(i)
Scriviamo una versione della funzione item() perché restituisca il totale di magazzino in termini di costo e quantità. Al solito provate a scrivere il codice e proseguite.
--- Segnalibro esercizio 2 ---
Per ora il codice è immediato:
local qty, tot = 0, 0
function item(t)
qty = qty + t.qty
tot = tot + t.qty * t.cost
end
dofile "dati.lua"
print(qty, tot)
Costruire l'albero ovvero mettere tabella dentro tabella
Normalmente il report dell'inventario viene strutturato per reparti o per fornitori, oppure ancora per classi di articolo, riportando i relativi totali. In generale un lavoro piuttosto noioso se non è supportato da software opportuni.Ammettiamo che il magazzino sia suddiviso in reparti e che a sua volta i reparti siano suddivisi per fornitore, a cui apparterranno i relativi articoli. Questa struttura è un albero.
Bene, scriveremo la nostra funzione item() in modo che costruisca l'albero corrispondente all'inventario di magazzino utilizzando una tabella che conterrà le tabelle dei reparti ciascuno contenente le tabelle dei fornitori, che ancora conterranno le tabelle degli articoli, traducendo esattamente la struttura con cui abbiamo deciso di organizzare il magazzino. Provateci prima di continuare.
--- Segnalibro esercizio 3 ---
Presa confidenza con la struttura a livelli il codice non è ne difficile ne lungo.
Invece di processare i dati record per record, creare l'albero significa caricare in memoria tutti i dati con l'obiettivo di tradurli in un report successivamente:
-- nuovo oggetto tabella d'inventario
local store = {}
-- main data processing function
function item(record)
-- livello principale: reparti
-- creo per comodità una variabile stringa per l'ID del reparto
local dep = record.department
-- creo la tabella relativa al reparto se ancora non esiste
if not store[dep] then
store[dep] = {}
end
-- var di comodo per il riferimento alla tabella di reparto
local tabdep = store[dep]
-- livello fornitore
-- variabile di comodo che contiene il codice del fornitore
local sup = record.supplier
-- se non esiste la tabella fornitore nel reparto la creo
if not tabdep[sup] then
tabdep[sup] = {}
end
-- livello articolo
-- vars di comodo alla tabella fornitore e al codice articolo
local tabsup = tabdep[sup]
local codeart = record.code
-- se il codice esiste aggiorniamo per quantità
-- altrimenti creiamo nuova tabella articolo per
-- la descrizione, il costo e la quantità
if tabsup[codeart] then
tabsup[codeart].qty = tabsup[codeart].qty + record.qty
else
tabsup[codeart] = {}
local ta = tabsup[codeart]
ta.descr = record.descr
ta.cost = record.cost
ta.qty = record.qty
ta.class = record.class
end
end
Raccolta dati
I vantaggi della struttura ad albero creata dalla funzione item() sono due: oltre a classificare per livelli gli articoli è possibile inserire lo stesso articolo con successive chiamate alla funzione. Durante la raccolta dati infatti capita che pezzi diversi dello stesso articolo vengano registrati in tempi diversi.La raccolta dati può essere effettuata connettendo un lettore di codici a barre a un notebook e gestendo i dati con un foglio elettronico o meglio con un database. In questo modo l'inventario procede molto velocemente e senza fatica, a condizione che sugli articoli sia presente il codice a barre tramite un etichetta per esempio, e che siano già stati inseriti i dati corrispondenti ai codici.
Visitare l'albero
Vorremo conoscere la quantità totale dei pezzi e il costo totale per ogni tipo di articolo (per esempio 'Diario', 'Forbici' o 'Quaderno').Disegnate la struttura della tabella creata dalla funzione 'item()' e poi scrivete il codice di reporting.
--- Segnalibro esercizio 4 ---
Ecco la mia versione del programma basata su una tabella dove le chiavi sono i nomi delle varie classi articolo e i corrispondenti valori sono tabelle con i campi quantità (qty) e costo (cost).
Il codice non è completo perché non vi ho riportato la funzione 'item()' che è la stessa vista prima, la creazione della variabile 'store' e la chiamata alla funzione 'dofile()'.
local function class_rpt(tree)
local class_data = {}
for _, dep in pairs(tree) do
for _, sup in pairs(dep) do
for code, item in pairs(sup) do
if class_data[item.class] then
local t = class_data[item.class]
t.qty = t.qty + item.qty
t.cost = t.cost + item.qty*item.cost
else
class_data[item.class] = {
qty = item.qty,
cost = item.qty*item.cost,
}
end
end
end
end
return class_data
end
-- print report
local class_data = class_rpt(store)
for class, tab in pairs(class_data) do
local fmt = "Class %20s: qty = %d, cost = %0.2f"
print(string.format(fmt, class, tab.qty, tab.cost))
end
Memorizzare tutto in un file
Per costruire il file si utilizzano le funzioni della libreria standard di Lua nel modulo io. Le impiegheremo per svolgere il prossimo passo che consiste nel memorizzare i dati ottenuti nell'esercizio precedente nel file "Classi.txt".La massima efficienza prevede di scrivere il file in un volta sola e di costruirne il contenuto con la funzione 'table.concat()' per evitare di dover concatenare stringhe cosa che produrebbe un enorme trasferimento di memoria come abbiamo già evidenziato in una delle puntate del corso.
Lascio a voi la tastiera e vi aspetto tra qualche riga dopo il segnalibro per presentarvi la mia soluzione del quesito.
--- Segnalibro esercizio 6 ---
Ecco la mia versione che sfrutta la funzione 'class_rpt()' precedentemente definita:
-- create the text file
local function make_class_rpt(fn, data, fmt)
local fmt = fmt or "Classe %-20s: qty=%6d, cost=%10.2f"
-- data assembly
local t = {}
for class, tab in pairs(data) do
t[#t+1] = string.format(fmt, class, tab.qty, tab.cost)
end
local s = table.concat(t, "\n")
-- apertura file
local f = assert(io.open(fn .. ".txt", "w"))
-- scrittura dati
f:write(s)
-- chiusura del file
f:close()
end
local filename = "Classi"
make_class_rpt(filename, class_rpt(store))
L'inventario
L'ultima parte del problema è generare il report principale. Occorre infatti visitare l'albero per trarne i totali dei vari livelli e produrre con essi la stampa. Per ragioni di tempo terremo semplice il codice lasciando irrisolti alcuni problemi come l'ordinamento in ordine alfabetico delle classi del nostro magazzino.Chiamiamo report() la funzione Lua che visita l'albero iterativamente. Come abbiamo già fatto prima useremo l'iteratore pairs per leggere i valori nelle tabelle dei vari livelli, iteratore che restituisce due argomenti la chiave e il suo valore senza un ordine predefinito.
Ecco le specifiche: l'inventario deve essere suddiviso per reparto con i totali di quantità e costo. Ciascun reparto deve essere suddiviso per fornitore con i relativi totali di quantità e costo. Per ogni fornitore è necessario creare la lista degli articoli con i quattro campi "Descrizione", "Quantità", "Costo". Infine il report dovrà essere memorizzato in formato testo in un file chiamato "Inventario.txt".
Disegnate la struttura della tabella creata dalla funzione 'item()' e poi scrivete il codice di reporting.
--- Segnalibro esercizio 7 ---
Bentornati!
La soluzione da conforntare con la vostra che vi riporto di seguito ha la possibilità di regolare la larghezza delle tre colonne dei dati impostando le tre variabili interne alla funzione 'report()'.
I campi non sono separati da un carattere di tabulazione perché il report cambierebbe allineamento in funzione del numero di caratteri spazio che l'editor in uso assegna alla tabulazione.
Inoltre il calcolo dei subtotali risulta essere il più semplice ed efficiente possibile perché il codice esegue somme di somme.
Ecco il programma Lua completo:
-- nuovo oggetto tabella d'inventario
local store = {}
-- main data processing function
function item(record)
-- livello principale: reparti
-- creo per comodità una variabile stringa per l'ID del reparto
local dep = record.department
-- creo la tabella relativa al reparto se ancora non esiste
if not store[dep] then
store[dep] = {}
end
-- var di comodo per il riferimento alla tabella di reparto
local tabdep = store[dep]
-- livello fornitore
-- variabile di comodo che contiene il codice del fornitore
local sup = record.supplier
-- se non esiste la tabella fornitore nel reparto la creo
if not tabdep[sup] then
tabdep[sup] = {}
end
-- livello articolo
-- vars di comodo alla tabella fornitore e al codice articolo
local tabsup = tabdep[sup]
local codeart = record.code
-- se il codice esiste aggiorniamo per quantità
-- altrimenti creiamo nuova tabella articolo per
-- la descrizione, il costo e la quantità
if tabsup[codeart] then
tabsup[codeart].qty = tabsup[codeart].qty + record.qty
else
tabsup[codeart] = {}
local ta = tabsup[codeart]
ta.descr = record.descr
ta.cost = record.cost
ta.qty = record.qty
ta.class = record.class
end
end
-- main reporting function
local function report(store)
local rpt = {}
local inv_qty, inv_cost = 0, 0
local inv_title = "Inventory report"
rpt[#rpt+1] = inv_title
rpt[#rpt+1] = string.rep("=", #inv_title).."\n\n"
-- column spacing
local descr_space, qty_space, cost_space = 28, 10, 12
local line_spaces = 2 + descr_space + qty_space + cost_space
-- in format string %% means '%'
local fmt_line = string.format("%%-%ds %%%dd %%%d.2f", descr_space, qty_space, cost_space)
for dep_name, tab_dep in pairs(store) do
local dep_qty, dep_cost = 0, 0
local dep_title = string.format("Department %s:", dep_name)
rpt[#rpt+1] = dep_title
rpt[#rpt+1] = string.rep("=", #dep_title).."\n"
for sup_name, sup_tab in pairs(tab_dep) do
local sup_qty, sup_cost = 0, 0
local sup_title = string.format("Supplier %s:", sup_name)
rpt[#rpt+1] = sup_title
rpt[#rpt+1] = string.rep("-", #sup_title)
for code, item in pairs(sup_tab) do
sup_qty = sup_qty + item.qty
sup_cost = sup_cost + item.qty*item.cost
rpt[#rpt+1] = string.format(fmt_line, item.descr, item.qty, item.cost)
end
rpt[#rpt+1] = string.rep("-", line_spaces)
rpt[#rpt+1] = string.format(fmt_line, "Total supplier", sup_qty, sup_cost)
rpt[#rpt+1] = ""
dep_qty = dep_qty + sup_qty
dep_cost = dep_cost + sup_cost
end
rpt[#rpt+1] = string.rep("-", line_spaces)
rpt[#rpt+1] = string.format(fmt_line, "Total department", dep_qty, dep_cost)
rpt[#rpt+1] = string.rep("-", line_spaces).."\n"
inv_qty = inv_qty + dep_qty
inv_cost = inv_cost + dep_cost
end
rpt[#rpt+1] = string.rep("=", line_spaces)
rpt[#rpt+1] = string.format(fmt_line, "Total inventory", inv_qty, inv_cost)
rpt[#rpt+1] = string.rep("=", line_spaces).."\n"
return rpt
end
-- create the text file
local function make_txt_file(fn, data)
-- apertura file
local f = assert(io.open( fn .. ".txt", "w"))
-- scrittura dati
f:write(table.concat(data, "\n"))
-- chiusura del file
f:close()
end
-- loading data
dofile "dati.lua"
-- report building
local rpt = report(store)
local filename = "Inventario"
make_txt_file(filename, rpt)
-- end
E questo è un frammento del file risultato che si ottiene con il codice precedente e i dati contenuti nel file:
Inventory report
================
Department SCRI:
================
Supplier BestWrite:
-------------------
971495 - Astuccio 80 16.00
678574 - Astuccio 81 5.00
643586 - Stilografica 11 1.00
934211 - Stilografica 61 24.00
596141 - Penna 41 13.00
...
... a lot of lines
...
290676 - Bianchetto 118 14.00
498096 - Cucitrice 108 8.00
518327 - Portamine 30 4.00
639929 - PuntiCucitrice 28 14.00
98644 - Gomma 4 1.00
113027 - PuntiCucitrice 90 12.00
----------------------------------------------------
Total supplier 5244 55662.00
----------------------------------------------------
Total department 44600 538322.00
----------------------------------------------------
====================================================
Total inventory 308783 3858599.00
====================================================
Conclusioni
Lo script è veloce e indipendente dal sistema operativo: legge un file di testo puro contenente i dati, li assembla nella struttura che corrisponde all'organizzazione reale del nostro magazzino e restituisce un file pronto per essere stampato nella forma voluta e nulla vieta con un ulteriore passaggio di compilazione, che l'inventario sia un report in formato PDF composto con LaTeX.L'idea si applica alla costruzione di report di dati complessi come un database cinematografico o un bilancio aziendale, oppure a inventari ancora più complessi per esempio per una catena di negozi.
Riassunto della puntata
Nella puntata abbiamo risolto alcuni problemi concreti con Lua. In particolare gli esempi di codice per l'elaborazione di dati mostrano interessanti applicazioni basate su file testuali in formato data description.Epilogo
Oggi finisce il corso che spero sia stato o vi sarà utile.Sono soddisfatto del lavoro compiuto e credo di avervi mostrato l'utilità pratica di Lua, questo fantastico piccolo grande linguaggio.
Rimangono inesplorati alcuni temi base di Lua come le coroutine, chissà se ci sarà una puntata extra in merito... magari con l'aiuto di qualcuno di voi.
Ringrazio Luigi che mi chiese di scrivere queste chiaccherate informatiche da pubblicare sul Blog "Lubit Linux" e ovviamente tutti i lettori.
-- exec with Lua
print("Alla prossima.\nR.")
Ciao
Etichette:
Lua
Iscriviti a:
Post (Atom)