SCRIPT BASH

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.

Vediamo il classico esempio di script, helloworld.sh:

#!/bin/sh
echo hello world
echo $?
				
L'output dello script sarà:

$ ./helloworld.sh
hello world
0
				

ISTRUZIONI CONDIZIONALI

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
				

CICLO FOR

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
				
Che restituisce:

$ ./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
				
Che restituisce:

$ ./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