Wiki Ubuntu-it

Indice
Partecipa
FAQ
Wiki Blog
------------------
Ubuntu-it.org
Forum
Chiedi
Chat
Cerca
Planet
  • Immutable Page
  • Info
  • Attachments


Problemi in questa pagina? Segnalali in questa discussione

Introduzione

Bash (acronimo per bourne again shell) è una shell del progetto GNU usata nei sistemi operativi Unix e specialmente in GNU/Linux. Si tratta di un interprete di comandi che permette all'utente di comunicare col sistema operativo attraverso una serie di funzioni predefinite o di eseguire programmi.

Tecnicamente bash è un clone evoluto della shell standard di Unix (/bin/sh), chiamata anche Bourne Shell dal nome del suo autore originario Stephen Bourne. Il nome esteso Bourne again shellun'altra shell Bourne») contiene un gioco di parole in quanto la sua pronuncia in lingua inglese risulta simile a «Born again shell» («shell rinata»).

In pratica bash può essere considerata come un processore di macro. Essa è infatti in grado di eseguire i comandi che le vengono passati o di interpretare un semplice linguaggio di programmazione che permette di combinare questi comandi tra di loro per svolgere compiti più complessi. In caso di necessità, è possibile raccogliere in file delle serie di comandi, in modo tale da creare script eseguibili contenenti variabili, funzioni e controlli di flusso, come nei più comuni linguaggi di programmazione.

Una delle altre maggiori funzionalità di bash è quella della redirezione dell'input e dell'output grazie al quale è possibile eseguire più programmi in cascata passando come input dell'uno l'output dell'altro.

GNU Bash è ricca di funzionalità sia per l'uso interattivo sia per lo scripting. Spesso però molte funzioni sono poco note.

Questa guida raccoglie (in maniera non esaustiva) diversi "trucchi" più o meno noti relativi Bash.

Scripting

Variabili

Le variabili in bash scripting non hanno bisogno di inizializzazione, l'assegnazione avviene utilizzando la sintassi:

VAR=valore

È molto importante che il valore sia scritto subito dopo l'uguale senza nessuno spazio. I riferimenti a tutte le variabili si scrivono anteponendo il carattere $ al nome della variabile:

VAR=world
echo hello $VAR!

Variabili speciali

  • $N dove N è un numero intero, corrisponde all'argomento N-esimo passato da terminale al programma ($0 è il nome del programma)

  • $* stringa che contiene tutti gli argomenti passati da terminale al programma

  • $# contiene il numero di argomenti passati da terminale al programma ($0 escluso)

  • $@ Contiene la lista dei paramentri passati allo script corrente. Ogni parametro viene opportunamente quotato e questo permette l'utilizzo di questa variabile nei cicli for per processare (ad esempio) una lista di nomi di file che possono contenere anche spazi. L'uso di questa variabile è quindi in genere consigliato rispetto a $* che ha la stessa funzione ma non quota i vari parametri.

  • $? Contiene il valore di uscita dell'ultimo comando o funzione. Il comando ha successo se ritorna zero, qualsiasi altro valore indica invece un codice di errore.

  • $$ contiene il PID del processo in esecuzione

  • $! contiene il PID dell'ultimo job in background

Esecuzione comandi

Dato che non è un vero linguaggio di programmazione, molte funzionalità non sono incluse nel bash scripting ma sono comunque utilizzabili tramite dei programmi esterni. Per prima cosa è utile sapere che se si vuole "catturare" l'output di un programma ed, ad esempio, inserirlo in una variabile allora si utilizza la sintassi:

VAR=`uname -r`
echo `pwd`

tramite i caratteri di back-quote (ALT GR + ') l'interprete bash esegue il comando e sostituisce con l'output tutta la chiamata; in questo caso, al posto di uname -r, è equivalente una scrittura del tipo:

VAR=2.6.21
echo /usr/src/linux

Programmi utili

  • expr: dato che non si possono eseguire semplici operazioni matematiche direttamente tramite l'interprete questo comando ci viene in aiuto

  • grep: utile per mostrare solo alcune righe di un determinato output

  • cut: serve per "tagliare" una stringa in tante sotto-stringhe in base ad un determinato separatore, per i programmatori java è molto simile allo StringTokenizer

  • cat: data l'assenza di funzioni proprie dell'interprete per l'apertura e la lettura dei file, questo comando apre il file e stampa il suo contenuto, l'output stampato può essere reindirizzato in una variabile come spiegato sopra

Per maggiori informazioni sui singoli comandi si rimanda ai relativi manuali dei programmi.

Manipolazione delle stringhe

Nelle shell *nix, storicamente, la manipolazione delle stringhe viene fatto attraverso programmi esterni alla shell come sed, awk e perl. Questi programmi vengono ancora usati quando si vuole mantenere la compatibilità con la shell sh, tuttavia imparare anche il solo sed (il più semplice dei tre) non è cosa immediata.

Se si usa Bash, non è necessario usare nessun programma esterno, ma basta imparare i tre operatori fondamentali ed alcuni concetti di base, per poter fare tutte le manipolazioni più comuni.

In Bash una stringa non è altro che una variabile, si indica dunque con ${nome} oppure con la forma abbreviata $nome. Il nome dentro le graffe può essere seguito da un modificatore che manipola la variabile, ad esempio:

 VAR="stringa-di-esempio"
 echo ${VAR#stringa-}

elimina "stringa-" dall'inizio della variabile.

I modificatori sono molti, ma possono essere facilmente ricordati se si imparano i tre fondamentali:

  • #: sottrae dall'inizio della stringa (minimale)

  • %: sottrae dalla fine della stringa (minimale)

  • / : sostituisce una sottostringa con un altra (solo la prima volta che viene incontrata)

Questi operatori sono minimali, questo vuol dire che se si usano le espressioni regolari per indicare la sottostringa (da eliminare o sostituire) verrà individuata in caso di ambiguità la sottostringa più piccola (o solo la prima nel caso della sostituzione).

Per ottenere gli operatori massimali basta raddoppiare il simbolo:

  • ##: sottrae dall'inizio della stringa (massimale)

  • %%: sottrae dalla fine della stringa (massimale)

  • //: sostituisce una sottostringa con un altra (tutte le volte che viene incontrata)

Gli operatori massimali cercano di individuare la sottostringa più grande che corrisponde all'espressione regolare (nel caso del modificatore // tutte le sottostringhe vengono sostituite). Gli operatori di questo tipo vengono comunemente chiamati anche greedy (ingordi).

Per una spiegazione dettagliata di tutti i modificatori e anche di altri modi di manipolare le stringhe in Bash (ad esempio expr) vedere: Advanced Bash-Scripting Guide: Manipulating Strings.

Esempio: Manipolazione delle stringhe

 VAR="questa.sarebbe.una.stringa.di.esempio"
 
                                    # Risultato:
 
 echo ${VAR#*.}        # --> sarebbe.una.stringa.di.esempio
 echo ${VAR##*.}     # --> esempio
 
 echo ${VAR%.*}       # --> questa.sarebbe.una.stringa.di
 echo ${VAR%%.*}    # --> questa
 
 echo ${VAR/st/ST}   # --> queSTa.sarebbe.una.stringa.di.esempio
 echo ${VAR//st/ST}  # --> queSTa.sarebbe.una.STringa.di.esempio

Alternativa a basename

Quando in uno script ci si deve riferire al nome dello script stesso è usuale utilizzare il comando (esterno a bash) basename. Tuttavia, tramite i modificatori del paragrafo precedente, Bash stessa è in grado di fornire questa funzionalità. Basta usare l'espressione ${0##*/}.

Esempio:

usage () {
        echo "usage: ${0##*/} "
        exit 1
}

Esempio: cambiare l'estensione ai file

Rinomina tutti i file *.txt della directory corrente in *.log:

for f in *.txt; do mv "$f" "${f/%txt/log}"; done

Condizioni

Le operazioni condizionali in bash possono essere eseguite in due modi, tramite il blocco if..then..else (simile al suo omonimo in c) o tramite il blocco case..in (simile allo switch).

If..Then..Else

Tutto il lavoro di questo blocco è svolto dal programma bash test, il suo uso è:

test [espr]

ci sono molte espressioni possibili le più comuni sono:

  • -f nomefile: ritorna vero se il file esiste

  • -d directory: ritorna vero se la directory esiste

  • str1 = str2: ritorna vero se la str1 è uguale alla str2

  • str1 != str2: ritorna vero se la str1 è diversa dalla str2

  • arg1 -eq arg2: confronto numerico, ritorna vero se arg1 è uguale a arg2

  • arg1 -ne arg2: confronto numerico, ritorna vero se arg1 è diverso a arg2

  • arg1 -lt arg2: confronto numerico, ritorna vero se arg1 è minore a arg2 (-le per maggiore o uguale)

  • arg1 -gt arg2: confronto numerico, ritorna vero se arg1 è maggiore a arg2 (-ge per maggiore o uguale)

  • espr1 -o espr2: concatena più condizioni, uguale all'or, ritorna vero o se l'espr1 o se l'espr2 ritorna vero

  • espr1 -a espr2: concatena più condizioni, uguale all'and, ritorna vero se sia l'espr1 che l'espr2 ritornano vero

Questo è un esempio d'uso del costrutto if:

if [ -f prova.txt ]
 then
       echo Il file esiste!
  else
       echo Il file non esiste!
fi

Come potete notare inserire tra parentesi quadre l'espressione da testare è equivalente a scrivere:

test -f prova.txt

Attenzione: l'if bash è molto rigoroso dal punto di vista sintattico, dopo l'espressione da valutare dovete andare a capo e scrivere la parola then, notereta anche che non c'è bisogno di parentesi graffe, infatti il blocco viene terminato con la parola chiave fi.

Case..in

L'uso del blocco case è molto semplice:

case $a in 
 1) echo sono un 1;;
 2) echo sono un 2;;
 3) echo sono un 3;;
 *) echo Non sono ne un 1 ne un 2 ne un 3;;
esac

viene valutata $a ed in base al valore contenuto vengono eseguite le operazioni associate.

Cicli enumerativi

Al contrario di altri linguaggi, proprio per l'utilizzo che si fà del Bash Scripting, i cicli sono del tipo enumerativo, cioè eseguono le operazioni per tutti gli elementi presenti un una lista indicata, il più importante è sicuramente il ciclo for..do.

For..do

La sua sintassi è:

for [VAR] [in [LIST]]
 do
    [COMANDI]
done

Il parametro dopo in è proprio la lista di cui parlavo prima, se ad esempio abbiamo un ciclo del tipo:

for i in 1 2 3 4 5
 do
    echo sono $i
done

il ciclo stamperà sullo standard output 1 2 3 4 5, altro esempio:

for i in `ls`
 do
    echo Sono il file $i
done

questo ciclo stamperà una lista di file, cioè il ciclo eseguirà per ogni singola parola dell'output di ls l'operazione di stampa a video.

Ulteriori risorse


CategoryProgrammazione CategoryDaRevisionare