mercoledì 30 gennaio 2008

Test compatti in shell

Il comando expr(1)
Il comando expr(1) consente di valutare espressioni aritmetiche, e il suo uso in generale è il seguente:

var=`expr val1 op val2`


dove var è la variabile alla quale sarà assegnato il valore calcolato, val1 e val2 sono i due operandi e op e l'operatore. Ad esempio:

var=`expr 10 + 20` var=`expr $var + 1`
che assegna prima a var il valore 30, e successivamente incrementa di 1 il valore calcolato, riassegnandolo nuovamente a var. Indubbimante expr è un comando molto potente, ma la shell ci mette a disposizione un modo molto più conveniente per eseguire operazioni matematiche: (( )). Ogni espressione racchiusa fra (( )) viene valutata nel suo contesto aritmetico direttamente. L'esempio precedente viene quindi riscritto come:
(( var = 10 + 20 )) (( var = $var + 1 ))
o ancora meglio
(( var = 10 + 20 )) (( var++ ))
A parte la maggiore compattezza del codice, bisogna considerare come (( )) non tenga conto degli spazi extra nell'assegnamento a variabile, cosa invece non tollerata dalla shell. Inoltre, expr restituisce il proprio risultato su stdout, e quindi deve essere catturato con i backtick per essere assegnato ad una variabile, mentre (( )) non restituisce nulla su stdout e assegna direttamente il valore calcolato alla variabile contenuta nell'espressione di assegnamento. Per entrambi il codice di ritorno ha la stessa semantica: 0 se il valore calcolato non è uguale a zero, 1 se il valore calcolato è uguale a zero.

Il comando test(1)

Il comando test(1) viene utilizzato per verificare determinate condizioni, ad esempio l'esistenza di un file, i permessi o il confronto fra valori stringhe e numerici. Il coamndo test(1) è un eseguibile presente su disco, ad esempio sulla mia macchina ho:
ls -l `which test`
-rwxr-xr-x 1 root root 23036 2007-09-29 14:51 /usr/bin/test

ls -l `which [`
-rwxr-xr-x 1 root root 25024 2007-09-29 14:51 /usr/bin/[

Il secondo programma, la parentesi quadra [, rappresenta una sorta di sinonimo per il comando test(1). In realtà non è un vero sinonimo, visto che i due programmi sono indipendenti (e non linkati). Tuttavia il comando test(1) può essere sostituito con la coppia di parentesi quadre, ad esempio:
if test -f $file
then
....
fi

diventa:
if [ -f $file ]
then
....
fi

L'equivalenza fra i due programmi si ha perfino dalla pagina man di test(1), dove i due sono presentati come equivalenti. Attenzione però che il comando [ da solo non funziona: la shell necessita che le parentesi siano bilanciate, e quindi [ deve essere sempre seguito da un ].


Test con operatori logici

Qualora si vogliano effettuare dei test usando [ al posto di test(1), si può ricorrere alla forma [[ e usare anche operatori logici e parentesi tonde per separare meglio i test. Ad esempio:


[[ (-f $file) && ( (-d data) || (-d tmp) ) ]]


questo test controlla l'esistenza di un file e l'esistenza di una directory fra data e tmp. Si noti la compattezza di una simile espressione, che sarebbe risultata invece molto più complessa con il solo uso dell'operatore test(1).


Un buon tutorial sugli operatori [ ] , [[ ]] e (( )) si può trovare presso la libreria IBM.

Nessun commento: