previous up

Introduzione allo Shell Scripting

index next

Subsections



2. Sintassi, variabili ed operatori

In questo capitolo si daranno le basi sintattiche della shell Bash, dando ampio spazio alla trattazione delle variabili e dei parametri. Verranno anche presi in considerazione argomenti quali gli operatori più importanti della shell Bash e le condizioni.


2.1 Sintassi di base

Uno dei modi migliori di introdurre gli elementi sintattici degli script di shell è partire dai commenti. In Bash, come in altre shell Unix, i commenti vengono individuati dal carattere #. Per la precisione, tutto ciò che segue ed è sulla stessa riga di # è da considerarsi un commento. Ad esempio le linee seguenti rappresentano commenti:

# Questo  un commento che si estende su una linea
#
# Questo  un commento
# piazzato su due linee
#
funzione() # questo  un commento piazzato dopo una funzione
#
Una caratteristica essenziale di uno shell script è quella di dover sempre iniziare con un uno strano simbolo: #! (che non è un commento!). Questa combinazione di caratteri viene chiamata Shee-Bang e serve a specificare quale deve essere l'interprete delle istruzioni che seguono. Nel nostro caso, il primo rigo di ogni script sarà:
#!/bin/bash
# Shee-Bang seguito dal percorso completo dell'interprete
#
# Seguono le istruzioni dello script

...


2.1.1 Parole speciali

Prima di procedere oltre, chiariamo che con ``parola'' si intende una qualsiasi sequenza di uno o più caratteri che Bash interpreta come una singola entità. Ciò detto, Osserviamo che Bash riserva alcune parole (Per la maggior parte comandi) per attribuir loro un significato speciale. Queste sono:

! case do done elif else fi for function if in
select then until while { } time [[ ]]
Queste parole possono essere usate al di fuori del loro significato speciale, ma con le dovute accortezze. Ad esempio, è perfettamente legale2.1 utilizzare una delle parole riservate come argomento di un comando:
[nico@deepcool nico]$ echo if
if
[nico@deepcool nico]$ echo function
function
Un altro modo per utilizzare le parole elencate consiste nel racchiuderle tra virgolette (Anche apici, si tratta comunque di quoting) o nel farle precedere dal carattere `` $\mathtt{\backslash}$''(Escaping). In questo modo, la shell non andrà incontro ad alcuna ambiguità nell'interpretare le istruzioni.




I tempi sono ormai sufficientemente maturi per cimentarci in un primo script, proviamo con il classico ``Ciao mondo'':

Esempio 2.1.1

#!/bin/bash
#
# Ciao mondo con la shell Bash

EXIT_SUCCESS=0

echo -e "Ciao mondo\n"

exit $EXIT_SUCCESS

Come funziona:

Lo script2.2 inizia, come necessario, con #!/bin/bash, seguito da due commenti. Successivamente viene definita la variabile EXIT_SUCCESS assegnandole il valore 0. La riga seguente fa uso di un comando presente all'interno della shell; echo serve a stampare sullo schermo del testo (per ragioni di portabilità echo è fornito anche come comando esterno, tramite il pacchetto GNU Shell Utils). È stato usato con l'opzione -e che consente di interpretare correttamente la sequenza di escape $\backslash$n , che rappresenta un ritorno a capo. Per maggiori informazioni, si digiti in un terminale man echo. Lo script termina con la riga exit $EXIT_SUCCESS. Anche exit è un comando interno alla shell (Bash built-in command) e serve in un certo senso a stabilire una comunicazione tra lo script e l'ambiente in cui viene eseguito. Una volta terminato, infatti, il nostro script dirà alla shell che tutto è andato per il verso giusto (codice 0). È convenzione che il valore di ritorno di uno script, o qualsiasi altro programma, sia 0 in caso di riuscita, un qualsiasi altro numero in caso d'errore2.3. Ad esempio, se un comando non viene trovato, il valore di ritorno del processo è 127; se il comando viene trovato, ma non è eseguibile, il valore di ritorno è 126.




In questo primo script abbiamo incontrato alcune novità, una di queste è rappresentata dalla definizione di una variabile. Questo argomento sarà oggetto della prossima sezione.


2.2 Variabili

Spesso capita di cucinare e di conservare le pietanze in contenitori per poi usarle in futuro. La shell fornisce ``contenitori'' analoghi, le variabili, nelle quali è possibile memorizzare valori per usarli in futuro o per maneggiarli più agevolmente.


2.2.1 Variabili locali

Nella sezione precedente abbiamo avuto già un primo incontro con le variabili. Abbiamo imparato in particolare come dichiararne una ed assegnarle un valore:
EXIT_SUCCESS=0
Figura 2.1: Schematizzazione dell'assegnazione di una variabile
\includegraphics[scale=0.6]{fig/var}
In fase di assegnazione, occorre fare attenzione a non lasciare spazi tra il nome della variabile il segno = ed il valore, in caso contrario la shell interpreterebbe = come un operatore (cfr. pag. [*], sez. 2.4). Un altro modo di assegnare una variabile fa uso del comando read , un'altro comando interno della Bash. Ad esempio, il seguente codice legge dalla tastiera un valore e lo assegna alla variabile $VAR:
read VAR
Si noti che nel dichiarare una variabile occorre sempre usarne il nome privo del simbolo ``$'', che va invece usato quando si deve far riferimento ad essa. Chiariamo la questione con un esempio:

Esempio 2.2.1

#!/bin/bash
#
# Dichiarazione di variabili

EXIT_SUCCESS=0
NOME=Nico

echo "Il mio nome  $NOME, il tuo?"
read TUO_NOME
echo "Ciao $TUO_NOME, buon divertimento con la shell!"

exit $EXIT_SUCCESS

Come funziona:

Lo script inizia con il solito #!/bin/bash (d'ora in poi non lo faremo più notare) e subito dopo vengono definite le variabili $EXIT_SUCCESS e $NOME2.4.




L'istruzione echo, successivamente, stampa sullo schermo il testo Il mio nome è Nico, il tuo? ed attende finché non viene scritto qualcosa e poi premuto il tasto return(RET). L'input letto dalla tastiera con read viene assegnato alla variabile $TUO_NOME che viene usata per stampare un messaggio di cortesia. Lo script ritorna alla shell il valore 0.


2.2.2 Variabili d'ambiente

Le variabili che abbiamo incontrato fino ad ora cessano di esistere non appena lo script termina. Nonostante ciò, esistono alcune variabili, dette d'ambiente che conservano nel tempo il loro valore. Tali variabili sono accessibili all'utente attraverso la parola chiave export2.5 in modo da garantirne un uso corretto. Occorre comunque notare che, anche usando export all'interno di uno script su di una variabile d'ambiente, i cambi a tale variabile rimarranno locali allo script e non si estenderanno alla shell che lo ha eseguito. Ciò accade perché uno script può esportare variabili solo ai suoi processi figli, cioè alle istruzioni in esso presenti. Risulta ovvio a questo punto che le variabili d'ambiente sono variabili impostate primordialmente dalla shell o altri programmi (Ad esempio login e telnet) e sono fruibili dai suoi processi figli (i comandi, gli script, ...).




Una lista di variabili globali può essere ottenuta digitando in console l'istruzione set. Alcune delle variabili più comuni sono2.6:




Cerchiamo di saperne di più.

Esempio 2.2.2

#!/bin/bash
#
# Uso delle variabili d'ambiente

EXIT_SUCCESS=0

echo "Informazioni sul sistema:"
echo -e "hostname:\t$HOSTNAME"
echo -e "hardware:\t$HOSTTYPE"
echo -e "OS:\t$OSTYPE\n"

echo "Informazioni sull'utente:"
echo -e "logname:\t$LOGNAME"
echo -e "homedir:\t$HOME"
echo -e "shell:\t$SHELL"
echo -e "path:\t$PATH\n"

echo -e "Directory di esecuzione: $PWD\n"

echo "Esportiamo un nuovo PATH..."

export PATH=${PATH}:/usr/games

echo -e "...il nuovo PATH :\n$PATH"

exit $EXIT_SUCCESS

Come funziona:

Lo script acquisisce alcuni dati tramite delle variabili d'ambiente stampandoli sullo schermo grazie al comando echo. È da notare l'uso della sequenza di escape $\backslash$t, che corrisponde ad un TAB . Per far interpretare correttamente la sequenza di escape, è necessario racchiudere tra virgolette la stringa che la contiene. Le righe seguenti ci insegneranno molto. Prima di tutto possiamo notare l'uso di export:
export NOME_VARIABILE=valore_della_variabile
o, equivalentemente
NOME_VARIABILE=valore_della_variabile
export NOME_VARIABILE
Un'altra novità è rappresentata dall'uso della scrittura ${PATH}. In realtà, questo è il vero modo per riferirsi ad una variabile, in genere si preferisce la più comoda forma $PATH, ma questa deve essere subito abbandonata quando si corre il rischio di incappare in ambiguità.




Come si può vedere dall'output dello script, il contenuto di $PATH sembra essere variato, ma se, finito lo script, digitiamo in terminale echo $PATH, possiamo renderci conto che il cambio della variabile è rimasto confinato nello ``spazio'' di esecuzione dello script.




Proviamo ora una versione leggermente modificata e più breve dello script precedente.

Esempio 2.2.3

#!/bin/bash
#
# ancora sulle variabili

EXIT_SUCCESS=0

echo "Informazioni sul sistema:"
echo -e "hostname:\t$(hostname)"
echo -e "hardware:\t$(uname -m)"

exit $EXIT_SUCCESS

Come funziona:

Come si può notare eseguendolo, il risultato di questo script è pressocché identico al precedente, la differenza sostanziale sta nel codice. Anziché utilizzare variabili d'ambiente, questa volta si è usato come variabile l'output del comando hostname prima e uname -m poi. Tali comandi sono stati racchiusi all'interno della combinazione di simboli $(...)2.7 che rappresenta per la Bash una sorta di variabile temporanea in cui memorizzare il risultato visibile di un comando (In realtà, ciò che si realizza è un'espansione di comandi).


2.3 Parametri

Un parametro è un'entità che immagazzina un valore; può essere indicato tramite un nome, un numero o un carattere speciale. Vediamo in questo modo che i parametri sono una generalizzazione delle variabili, infatti una variabile è un caso di parametro identificato da una parola.




Immaginiamo di lanciare un nostro script in maniera un po' differente, supponiamo di farlo scrivendo in un terminale:

[nico@deepcool intro]$ ./script param1 param2 param3
Come sfrutterà lo script queste informazioni aggiuntive? Ritornerà un errore?
Chiariamo il tutto con un esempio.

Esempio 2.3.1

#!/bin/bash
#
# Utilizzo dei parametri posizionali

EXIT_SUCCESS=0

echo "Hai inserito ${1}, $2 e $3 per un totale di $# parametri"

exit $EXIT_SUCCESS

Come funziona:

Lo script si sviluppa su un'unica riga; $12.8, $2 ed $3 rappresentano rispettivamente il primo, secondo e terzo parametro passato allo script, mentre $# contiene il numero di parametri passati.




Proviamo ad eseguire lo script:

[nico@deepcool intro]$ ./script param1 param2 param3
Hai inserito param1, param2 e param3 per un totale di 3 parametri
Sembra funzionare bene, ma cosa succederebbe se inserissimo quattro parametri anziché tre? Per il momento lasciamo in sospeso questa domanda, promettendo di occuparcene più in avanti nel capitolo 3.




I parametri disponibili all'interno di uno script non si esauriscono di certo qui, alcuni ulteriori sono2.9:




È importante chiarire la differenza che corre tra $* e $@; la prima scrittura fornisce tutti i parametri posizionali visti come un'unica parola, mentre la seconda fornisce tutti i parametri posizionali ognuno come singola parola. Questa distinzione sarà importante in futuro.


2.3.1 Espansione di parametri

In precedenza, abbiamo già incontrato la forma ${VARIABILE} (sezione 2.2.2) ed abbiamo affermato che questo è il modo più generale per riferirsi ad una variabile. Tuttavia, il simbolo ${ ... } ha un ruolo ben più importante, poiché rappresenta la forma più generale per consentire alla shell di espandere parametri. Nel caso di ${VARIABILE} il parametro è la variabile $VARIABILE e l'espansione è il suo valore.




Vediamo ora alcune delle altre forme di espansione offerte dalla shell Bash.


2.4 Operatori e condizioni

Una condizione è un particolare avvenimento per il quale è lecito domandarsi se sia vero o meno. Le condizioni fanno parte della vita quotidiana di ogni persona; ogni nostra azione, ad esempio, ha luogo solo in virtù di determinate circostanze. Se vediamo l'indicatore del carburante nella zona rossa, è del tutto naturale andare a fare rifornimento; ciò accade perché abbiamo valutato la condizione fornitaci dalla lancetta dell'indicatore. La shell Bash, pur non funzionando a benzina, fa altrettanto; valuta le condizioni che le vengono fornite ed agisce di conseguenza.




Valutare una condizione è una caratteristica essenziale per ogni linguaggio di programmazione, pertanto verranno elencati alcuni degli operatori più importanti della shell Bash.


2.4.1 Operatori su numeri

Divideremo gli operatori che agiscono su numeri in due classi:
-
Operatori di confronto:
quelli che eseguono un controllo circa l'ordine tra due numeri.
-
Operatori aritmetici:
quelli che manipolano i numeri per ottenerne di nuovi.


2.4.1.1 Operatori di confronto

I seguenti sono operatori binari su numeri, ovvero agiscono su 2 numeri


2.4.1.2 Operatori aritmetici

Oltre alle 4 operazioni, la shell Bash è dotata di altri operatori aritmetici, molti dei quali sono simili a quelli del C. La shell consente di eseguire calcoli utilizzanto alcune sintassi particolari. Occorre, però, notare che è possibile eseguire solo operazioni su numeri interi; per questo motivo, il risultato di calcoli come 2 / 3 viene arrotondato al più grande intero minore o uguale al risultato (Parte intera). Per effettuare calcoli con numeri in virgola mobile, si può utilizzare il comodo programma bc .




Il calcolo di operazioni aritmetiche può essere effettuato utilizzando il comando expr , o il comando interno let , oppure racchiudendo l'espressione da valutare nel simbolo $(( ... )) (Espansione aritmetica). Inoltre, possono anche essere usata la forma (( ... )), che non produce alcun output, ma valuta solamente l'espressione aritmetica contenuta al suo interno.

Esempio 2.4.1

#!/bin/bash
#
# Esecuzione di calcoli
EXIT_SUCCESS=0

echo $(( 2 / 3 ))
echo $(( 5 + 5 / 2 ))
echo $(( $(( 5 + 5 )) / 2 ))
echo $(( 2 ** 8 ))

exit $EXIT_SUCCESS

Come funziona:

L'esempio riportato illustra l'uso di alcuni semplici operatori aritmetici e del simbolo $(( ... )). Le precedenze tra gli operatori sono uguali a quelle usate comunemente, ad esempio 5 + 5 / 2 equivale a 5 + (5 / 2).
L'esempio ci dice anche che è possibile annidare più simboli $(( ... )) nel calcolo di una espressione.




Si tenga presente che sono legali anche le forme ``alla C'' +=, -=, *=, /= e %=; queste devono essere interpretate come:

VARIABILE_1(OP)=$VARIABILE_2
        equivale a
VARIABILE_1=$(( $VARIABILE_1 (OP) $VARIABILE_2 ))
dove (OP) è uno tra +, -, *, / e %.

Esempio 2.4.2

#!/bin/bash
#
# Esecuzione di calcoli (2)
EXIT_SUCCESS=0

VARIABILE=10

echo $VARIABILE

(( VARIABILE+=10 ))

echo $VARIABILE

(( VARIABILE/=10 ))

echo $VARIABILE

exit $EXIT_SUCCESS

Come funziona:

L'esempio illustra l'uso delle forme (OP)= nonché quello di (( ... )). La forma (( ... )), come detto, non produce alcuna espansione, ma si limita a modificare il valore di $VARIABILE.


2.4.2 Operatori logici

Di seguito saranno riportati gli operatori logici forniti dalla shell Bash e se ne chiarirà il significato nella sezione 2.6.


2.4.3 Operatori su stringhe

Riportiamo gli operatori su stringhe; la maggior parte è binaria, solo due operatori sono unari.




Per usare < e > occorre fare attenzione a precederli con il carattere di escape `` $\mathtt{\backslash}$''o racchiuderli tra virgolette (O apici), la shell altrimenti li interpreterebbe come operatori di input/output, come vedremo nella sezione 2.4.5


2.4.4 Operatori su file

Gli operatori su file sono per la maggior parte operatori unari (accettano un solo input), tranne gli ultimi 3 di questa lista, che sono binari. Ritornano tutti un valore booleano (vero o falso) a seconda che il test effettuato abbia avuto successo o meno.


2.4.5 Semplici operatori di Input/Output

Verranno elencati ed introdotti alcuni semplici e fondamentali operatori per gestire l'I/O (Input/Output) di programmi, in modo da rendere più divertenti gli esempi.

2.4.5.1 | (pipe)

L'operatore | (pipe, tubo) consente di trasformare l'output di un comando in input di un altro. Volendo essere più specifici, si può dire che tale operatore consente di rendere standard input di un programma lo standard output di un altro. L'utilità di tale operatore è inestimabile.




Consideriamo il comando

[nico@deepcool nico]$ cat /etc/passwd | grep bash
root:x:0:0:root:/root:/bin/bash
nico:x:500:500:Domenico Delle Side:/home/nico:/bin/bash
ed analizziamo cosa è accaduto. cat è un programma che stampa sullo standard output (lo schermo nel nostro caso) il contenuto dei file passati come argomento. grep, invece, serve per ricercare una particolare espressione all'interno di un testo che può essere contenuto in un file oppure scritto sullo standard input. La sequenza di comandi data, dunque, si può riassumere dicendo che attraverso |, il contenuto del file /etc/passwd viene passato a grep che cerca poi all'interno del testo la parola bash.

2.4.5.2 <

L'operatore < consente di reindirizzare il contenuto di un file facendolo diventare, ad esempio, standard input di un comando. Il comando
[nico@deepcool nico]$ mail nico < /etc/passwd
fa comparire per incanto nella mia casella locale di posta il contenuto del file /etc/passwd.

2.4.5.3 > e »

Gli operatori > e » svolgono entrambi un compito circa analogo, ambedue infatti si occupano del reindirizzamento di un output. Questi operatori possono essere utilizzati per scrivere il risultato di un comando in un file, tuttavia, presentano una piccola differenza, chiariamo il tutto con un esempio.
[nico@deepcool nico]$ man bash > bash
[nico@deepcool nico]$ ls -lh bash
-rw-rw-r--    1 nico     nico         293k Jul 24 19:59 bash
[nico@deepcool nico]$ man bash >> bash
[nico@deepcool nico]$ ls -lh bash
-rw-rw-r--    1 nico     nico         586k Jul 24 19:59 bash
[nico@deepcool nico]$ man bash > bash
[nico@deepcool nico]$ ls -lh bash
-rw-rw-r--    1 nico     nico         293k Jul 24 19:59 bash
Analizziamo ciò che è accaduto. Il primo comando man bash > bash reindirizza lo standard output del comando man all'interno del file /home/nico/bash; dato che tale file non esisteva in precedenza, > si occupa di crearlo. Il risultato finale è, come è possibile vedere attraverso il comando ls -lh, un file di testo da 293 Kb contenente la pagina manuale di bash.
Il comando successivo, man bash » bash, opera lo stesso reindirizzamento, tutavia, constatando che il file /home/nico/bash è già esistente, lo apre aggiungendo l'output di man bash al testo già presente nel file. Come era ovvio aspettarsi, otteniamo un file di dimensione doppia (586 Kb).
Se eseguiamo nuovamente man bash > bash, noteremo che il file originario è stato troncato e poi sovrascritto.


2.4.6 Operatori su bit

Prima di trattare questo argomento, occorre fare una piccola trattazione sulla rappresentazione binaria dell'informazione.

2.4.6.1 Rappresentazione binaria

All'interno di un calcolatore, l'informazione è rappresentata a livello di tensione che può ``accendere'' o ``spegnere'' determinati circuiti. Di conseguenza, ogni informazione può essere convenientemente espressa in termini di due stati che descrivono la situazione in cui si trovano degli ipotetici interruttori che azionano tali circuiti. Per convenzione, si indicano queste configurazioni con 1 (acceso) e 0 (spento).
Ogni informazione presente in un calcolatore è dunque rappresentata da sequenze di numeri del tipo 1011001011010001, in cui ogni istanza di 1 o 0 rappresenta un bit , ovvero l'unità di memoria elementare di un calcolatore. Ad esempio, anche i numeri naturali vengono rappresentati sotto forma binaria (0 = 0000, 1 = 0001, 2 = 0010, 3 = 0011, 4 = 0100, 5 = 0101, 6 = 0110, 7 = 0111, 8 = 1000, 9 = 1001, ecc...).
Gli operatori su bit consentono di eseguire operazioni direttamente su queste quantità. Elenchiamo di seguito quelli offerti dalla shell Bash:

Presentiamo ora un simpatico esempio.

Esempio 2.4.3

#!/bin/bash
#
# Potenze del due tramite operatori su bit. 

EXIT_SUCCESS=0

echo "Inserisci l'esponente della potenza di 2 che vuoi conoscere"
echo "(vale solo per esponenti positivi): "

read ESPONENTE

echo "2^($ESPONENTE) vale: $(( 2 << $(( $ESPONENTE - 1 )) ))"

exit $EXIT_SUCCESS

Come funziona:

Lo script sfrutta una nota proprietà dello spostamento di un bit a sinistra, questa operazione, infatti, equivale alla moltiplicazione per due del numero dato. In questo modo è possibile ottenere in maniera molto veloce le potenze di due, spostandosi a sinistra di un numero pari all'esponente diminuito di una unità (il primo due lo abbiamo già, quindi dobbiamo toglierlo).


2.5 Liste di comandi

Uno delle caratteristiche più utili delle shell Unix è la possibilità di poter concatenare dei comandi e condizionare agevolmente l'esecuzione di uno in luogo dell'altro. Questa possibilità è offerta da una serie di operatori elencati di seguito.


2.6 Uso degli operatori

Dopo aver passato in rassegna i più importanti operatori offerti dalla shell Bash, vediamo come utilizzarli con maggiore dettaglio.




Innanzitutto, occorre capire come è possibile valutare una condizione, cioè come eseguire dei test. Niente di più facile, esiste il comando interno test che da alla shell la possibilità di valutare la veridicità della condizione che gli si fornisce. Accanto a test, esiste anche il simbolo [ ... ] che consente alla shell di valutare la condizione interna. Esiste anche una terza via per valutare condizioni ed è fornita da [[ ... ]], analogo ai precedenti e con qualche facilitazione aggiunta (consultare la pagina manuale o il manuale info di Bash per maggiori informazioni), tuttavia è presente solo sulle versioni più recenti di Bash (dalla versione 2.02). Inoltre, è meglio non mettere troppa carne al fuoco; in questo momento sarete così presi da questa interessantissima ed avvincente guida che rischiereste di bruciarla, un vero peccato!




Come primo esempio, vediamo come è possibilire utilizzare gli operatori logici e le differenze che corrono tra loro. Prima di tutto occorre esaminare come si compongono le condizioni con AND, OR e gli operatori di lista. Un AND logico è vero se e solo se sono vere tutte le condizioni che lo compongono, mentre un OR è falso se e solo se sono false tutte le condizioni che lo compongono (quindi vero negli altri casi).

Esempio 2.6.1

#!/bin/bash
#
# Uso degli operatori logici

EXIT_SUCCESS=0

[ -e $HOME/.bashrc ] && echo "Nella mia home  presente .bashrc"
[ ! -e $HOME/non_esisto ] && echo "Il file non_esisto non esiste!"

[ ! -e $HOME/.bashrc ] || echo "Nella mia home  presente .bashrc"
[ -e $HOME/non_esisto ] || echo "Il file non_esisto non esiste!"

exit $EXIT_SUCCESS

Come funziona:

Per ogni riga di codice, a meno di situazioni strane, l'esempio stamperà sullo schermo il relativo messaggio. Vediamo in dettaglio cosa accade. \fbox{\texttt{[ -e \texttt{\$HOME}/.bashrc ]}} verifica la presenza del file .bashrc nella home directory di chi lo esegue, poiché questa guida è basata sulla shell Bash, è ragionevole supporre che questo file esista, dunque la condizione sarà vera. In questa situazione, l'operatore && si preoccuperà di eseguire il comando seguente echo ``Nella mia home è presente .bashrc'' , che stamperà sullo schermo il messaggio ritornando un valore di successo. La seconda condizione ( \fbox{\texttt{[ ! -e \texttt{\$HOME}/non\_esisto ]}}) valuterà la non esistenza, nella home directory dell'esecutore, del file non_esisto; non è un nome di file comune quindi non dovrebbe esistere pertanto negando la condizione attraverso l'operatore ! otterremo una condizione vera e verrà pertanto stampato sullo schermo il messaggio successivo, come prima.




Sappiamo già che in $HOME esiste .bashrc, dunque il contrario è falso, pertanto nella riga successiva, l'operatore || consentirà l'esecuzione del comando successivo, stampando il messaggio sullo schermo. Analogamente, il test successivo è falso e verrà nuovamente stampato un messaggio sullo schermo.

Esempio 2.6.2

#!/bin/bash
#
# Uso degli operatori logici (2)

EXIT_SUCCESS=0

[ -e $HOME/.bashrc -a ! -e $HOME/non_esisto ] && \
   echo "Nella mia home esiste .bashrc e non c' non_esisto"

[ -e $HOME/non_esisto -o -e $HOME/.bashrc ] && \
   echo "Nella mia home non c' non_esisto, ma si trova .bashrc"

exit $EXIT_SUCCESS

Come funziona:

In questo esempio capiamo la differenza che corre rispettivamente tra gli operatori ``-a - &&'' e ``-o - ||''. Infatti, -a e -o sono operatori che collegano logicamente delle condizioni all'interno di un test, mentre && e || collegano ``logicamente'' dei comandi2.10. In altre parole \fbox{\texttt{-e \$HOME/.bashrc -a ! -e
\$HOME/non\_esisto}} è una condizione composta tramite l'operatore logico -a (AND) e risulta vera quando tutte le sotto-condizioni che la compongono sono vere. Allo stesso modo, anche \fbox{\texttt{-e \$HOME/non\_esisto -o -e \$HOME/.bashrc}} è una condizione composta, questa volta tramite l'operatore logico -o (OR) e risulta vera quando almeno una delle due sotto-condizioni è vera.




Gli operatori && e ||, invece, collegano comandi in base al loro valore di ritorno, come abbiamo visto nell'esempio precedente.

previous up

Introduzione allo Shell Scripting

index next

Domenico Delle Side 2002-09-24