2. BASH SCRIPTING
• La shell è l'interfaccia fra utente e sistema
operativo.
• L'avete già usata per esempio quando
“aprite una finestra terminale” e digitate “ls”.
• Esistono diverse shell ( Bourne, cshell,
Korn ) la bash ( Bourne Again Shell) è nata
come progetto GNU ed è una delle più
diffuse in Linux.
3. Redirezione dell'Output
• Provate il comando :
echo 1234 / 2
1234 / 2
• Se usiamo l'operatore > possiamo scrivere
l'output in un file
echo 1234 / 2 > mycalc
• In questo caso non viene stampato nulla
ma la stringa 1234 / 2 viene scritta nel file
mycalc
4. Redirezione dell'Output
• Se usiamo l'operatore | possiamo scrivere
l'output come input di un'altro comando
echo 1234 / 2 | bc
617
• Con l'operatore < posso prendere il
contenuto del file appena scritto e usarlo
come input del comando bc
bc < myfile
617
5. Redirezione dell'Output
• L'operatore >> aggiunge l'output ad un file esistente
echo 444 / 2 >> myfile
bc < myfile
617
222
• L'operatore ` op ` oppure $( op ) implica che
l'operazione op fra i due apici o parentesi deve essere
calcolata prima di essere inviata in output
echo `echo 1234 /2 | bc` + 1 | bc
618
6. Il primo script
• Possiamo ora creare il primo script :
echo #!/bin/bash > myscript
echo C=`expr $1 + $2` >> myscript
echo echo $C >> myscript
• Per visualizzarlo:
cat myscript
• Prima di eseguirlo dobbiamo rendere il file myscript
eseguibile
chmod +x myscript
./myscript 23 4
27
7. Il primo script
• Una volta creato uno script diviene un vero e proprio nuovo
comando. L'espressione $(( op )) significa “il valore
numerico di” op.
echo $(( $(./myscript 23 3 ) + 1))
27
echo $(( $(./myscript 22 4 ) + 1)) + 1 | bc
28
• Se volessimo usare myscript senza il suffisso ./ dovremmo
metterlo in una delle directory elencate nella variabile
d'ambiente PATH
echo $PATH
/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin
8. Variabili d'ambiente
• In ambiente UNIX ogni processo nasce da un'altro ( il processo 0 è parte del
kernel, 1 è chiamato init ) e ogni processo il suo insieme di variabili d'ambiente
( shell ) che eredita dal processo che da cui è stato generato, può modificare
e trasmettere ai processi che genera.
• Quando “aprite una finestra terminale” lanciate un processo ( bash ) da cui
potete lanciarne altri. Per visualizzare le variabili d'ambiente definite:
printenv
• Per definire o modificare una variabile d'ambiente e trasmetterla ai processi
generati si usa il comando export.
export PATH=$PATH:/il/mio/percorso/
• Non è possibile per un processo modificare l'ambiente di chi lo ha generato.
9. Variabili d'ambiente
Sono stringhe di caratteri che contengono informazioni che sono accessibili sia da script
•
che da programmi C.
#include <stdio.h>
#include <stdlib.h> // setenv è definita qui.
int main()
{
char *myenvvar=getenv("PATH");
printf("La variabile d'ambiente PATH è %sn", myenvvar);
return 0;
}
Usando l'operatore ${ myvar } si espande esplicitamente il contenuto di una variabile
•
d'ambiente in uno script. Nella riga seguente notate l'uso del ; per dividere più comandi.
echo $PATH ; echo caratteriprima${PATH}caretteridopo ; echo $PATH:/mypath/.
Per eliminare la definizione di una variabile d'ambiente usate il comando unset
•
unset PATH
10. CICLI
• Un esempio di ciclo:
for x in uno due tre ;do echo $x; done
uno
due
tre
• Alla variabile x sono stati assegnati i valori uno due tre e stampati. Ma
possiamo farlo anche col contenuto di una directory. O col risultato di
un comando
for x in $PWD/* ;do echo $x; done
for x in $(pwd)/* ;do echo $x; done
• Equivale ad un ls a questo punto potremmo applicare un comando ad
ogni file in una directory. PWD è una variabile d'ambiente che contiene
il path della directory corrente. Mentre $(pwd) significa “il risultato del
comando pwd. * è l'usuale sostituzione per dire * qualunque carattere
e / il separatore delle directory.
11. Esecuzione Condizionale
• Vediamo ora di modificare il comando precedente per
agire solo su alcuni files.
Il metodo più semplice:
for x in $(ls $(pwd) | grep .cpp);do echo $x; done
• In questo caso abbiamo usato il comando ls e il comando
grep. Il secondo intercetta l'output del primo e manda in
output solo le stringhe che contengono la sottostringa
.cpp
• Il metodo con confronto diretto notate le “ “ che servono
in generale se si hanno stringhe con spazi:
for x in $(pwd)/* ;do if [ "${x##*.}" = "cpp" ] ; then
echo $x; fi; done
12. Programmazione Funzionale
• Analisi dettagliata della riga:
for x in $(ls $(pwd) | grep .cpp);do echo $x; done
Il comando pwd produce un risultato che serve al comando ls per
produrre dati che vengono mandati tramite una pipe al comando grep. Le
stringhe che risultano da questa operazione vengono assegnate a x e
l'operazione echo $x viene eseguita su queste.
Questo modo di programmare ove un flusso di dati viene inviato da una
funzione ad un'altra e si possono combinare fra loro più funzioni è
chiamato paradigma funzionale.
Altri linguaggi usano altri paradigmi di programmazione.
Per approfondire con un mio collega della Stanford University:
http://www.youtube.com/playlist?list=PL9D558D49CA734A02
Seguite ALMENO la sua prima lezione per avere un'idea di che si parla.
13. Esecuzione Condizionale
for x in $(pwd)/* ;do if [ "${x##*.}" = "cpp" ] ; then echo $x; fi; done
• X##*. significa “rimuovi la stringa più lunga prima di *. ovvero se c'era un
file chiamato tizio.caio.sempronio.cpp il risultato era cpp.
• La condizione dell'if è racchiusa fra [ ], la sintassi completa è:
if [ condizione ]
then
azione
elif [ condizione2 ]
then
azione2
...
else
azioneX
fi
• Tutte le condizioni vengono verificate e se nessuna di queste è vera allora
si attiva l'else con l'azioneX
14. Manipolazione di Stringhe
• È un' argomento vasto. Qualche esempio:
stringZ=il.mio.file.cpp
echo ${stringZ#*.} # rimuove la stringa più corta prima di *.
mio.file.cpp
echo ${stringZ##*.} # rimuove la stringa più lunga prima di *.
cpp
echo ${stringZ%.*} # rimuove la stringa più corta dopo .*
il.mio.file
echo ${stringZ%%.*}
il
• Maggiori dettagli su:
• http://tldp.org/LDP/abs/html/string-manipulation.html
• Awk è un programma potentissimo per la manipolazione di stringhe. Un
piccolissimo esempio:
ls -l | awk '/.cpp/ {print $5,$9}'
• Cerca fra le stinghe quelle che contengono .cpp ( che è una regular expression ) e
stampa i campi 5 e 9 ( dimensione e nome )
15. Altre forme di cicli
• While è un ciclo che si ripete finché la condizione è valida
mentre until viene interrotto quando la condizione è valida:
while [ condizione ]
do
istruzioni
done
until [ condizione ]
do
istruzioni
done
16. Case
• Case equivale allo switch del C:
for x in $(pwd)/* ;
do
case "${x##*.}" in
cpp) echo file c++ $x;;
pdf) echo file pdf $x ;;
*) echo non riconosciuto;;
esac;
done
17. Funzioni
• I parametri sono passati come da riga
comando e richiamati allo stesso modo può
essere un modo per aggiungere comandi.
myfunction(){
for x in $1/* ;
do
case "${x##*.}" in
cpp) echo file c++ $x;;
pdf) echo file pdf $x ;;
*) echo non riconosciuto;;
esac;
done
}
18. Librerie
• Possiamo scrivere una libreria di funzioni e includerla in uno
script tramite il comando source o l'operatore “.” .
• Se la funzione scritta precedentemente è stata scritta in un file
chiamato libexample allora uno script può richiamarla
#!/bin/bash
. /il/percorso/completo/libexample
# Oppure source /il/percorso/completo/libexample
myfunction $PWD