Gli script bash (con estensione .sh) rappresentano veri e propri programmi che utilizzano i comandi disponibili su qualsiasi sistema operativo Unix. Tali script possono essere scritti con qualsiasi editor di testo (Gedit, vi, TextPad...) e richiedono permessi di esecuzione:
$ chmod +x myscript.sh
Uno script può essere eseguito col commando:
$ ./myscript.sh
La prima riga del file deve essere:
#!/bin/sh
che indica quale programma utilizzare per eseguire lo script. Tutte le righe che iniziano con # sono interpretate come commento (e quindi non vengono eseguite), tranne la prima che definisce il programma da usare.
In uno script bash si possono utilizzare variabili, cicli e istruzioni condizionali come in un normalissimo linguaggio di programmazione. Inoltre possiamo passare dei parametri allo script quando ne richiediamo l’esecuzione:
$ ./myscript.sh arg1 arg2 …
Con il carattere speciale $ è possibile accedere a tali parametri:
$1 è il primo parametro
$2 il secondo
....
$0 è il nome del programma stesso
$* è la concatenazione di tutti i parametri, senza $0
$# ritorna il numero dei parametri
$$ è il pid della shell
$! è il pid dell'ultimo processo lanciato.
$? è il valore di ritorno (l'exit status) del comando, che vale 0 se tutto il programma è stato eseguito correttamente, diverso da 0 se c'è stato qualche problema.
helloworld.sh
:
#!/bin/sh
echo hello world
echo $?
$ ./helloworld.sh
hello world
0
Iniziano con if e terminano con fi. La condizione è data dal comando test, che può essere utilizzato anche mediante parentesi quadre.
x="UTF-8"
if [ $x == *UTF* ]; then
echo OK
else
echo ERROR
fi
dove la condizione poteva anche essere scritta come:
if test $x == *UTF8*;.
Questo programma
assegna alla variabile x una stringa e verifica che poi che tale
stringa contenga la sottostringa "UTF". Si notino gli spazi dopo la prima parentesi
quadra e prima della seconda, come pure il punto e virgola dopo la
condizione di test. È possibile unire più condizioni utilizzando gli
operatori logici AND e OR:
if [[ $x == *$y* ]] || [[ $x == *$z* ]]; then
if [[ "$year" != "" && "$code" != "" ]]; then
La prima istruzione controlla se il contenuto della variabile x comprende quello della variabile y o z (gli asterischi * fanno parte delle espressioni regolari e rappresentano qualsiasi carattere), mentre la seconda istruzione verifica che entrambe le variabili year e code non contengano la stringa vuota.
I test di tipo aritmetico e su stringhe si fanno con operatori diversi:
-lt | < |
-gt | > |
-le | <= |
-ge | >= |
-eq | == |
-ne | != |
= | equal |
!= | not equal |
< | less then |
> | greater then |
-n s1 | string s1 is not empty |
-z s1 | string s1 is empty |
Il seguente script, ad esempio, richiede all'utente un input, che deve essere un numero compreso tra 1 e 3. Stampa una stringa diversa a seconda dell'input, richiedendo una nuova scelta nel caso di input non valido:
#!/bin/bash
# Declare variable choice and assign value 4
choice=4
# Print to stdout
echo "1. Bash"
echo "2. Scripting"
echo "3. Tutorial"
echo -n "Please choose a word [1,2 or 3]? "
# Loop while the variable choice is equal 4
while [ $choice -eq 4 ]; do
# read user input
read choice
# bash nested if/else
if [ $choice -eq 1 ] ; then
echo "You have chosen word: Bash"
else
if [ $choice -eq 2 ] ; then
echo "You have chosen word: Scripting"
else
if [ $choice -eq 3 ] ; then
echo "You have chosen word: Tutorial"
else
echo "Please make a choice between 1-3 !"
echo "1. Bash"
echo "2. Scripting"
echo "3. Tutorial"
echo -n "Please choose a word [1,2 or 3]? "
choice=4
fi
fi
fi
done
Inizia con for e termina con done. Quando si usa la variabile dichiarata nella condizione di ciclo occorre utilizzare il simbolo $. L’iterazione è su stringhe, non su numeri come accade nei normali linguaggi di programmazione.
for i in a b c d e ; do
echo $i
done
$ ./myscript.sh
a b c d e
Si possono fare anche iterazioni su liste. Ad esempio, per iterare su una sequenza di numeri:
for i in `seq 1 5` ; do
echo a$i
done
$ ./myscript.sh
a1 a2 a3 a4 a5
Si noti l’utilizzo del carattere backquote, che causa l’esecuzione dell’istruzione contenuta, cioè la shell lo sostituisce con l’output del programma. Si noti anche come vengono concatenate le stringhe: a$i fa sì che il carattere a venga concatenato al contenuto della variabile i.
Vediamo anche come sia possibile iterare su una lista di nomi di files, ottenuta col comando find (consideriamo tutti gli XML nidificati nella directory corrente):
# tutti i files XML
LIST=`find . -name "*.xml"`
UTF8="utf-8"
# scan files
for file in $LIST; do
# estrae il contenuto del file nella variabile x
x=`cat $file`
# controlla se il file contiene la parola “utf-8”
if [ $x == *$UTF8* ]; then
echo OK
else
echo NO
fi
done