Ci sono due casi in cui trovo :
utile:
Assegnazioni di variabili predefinite
#!/bin/sh
# set VAR to "default value" if not already set in the environment
: "${VAR=default value}"
# print the value of the VAR variable. Note that POSIX says the behavior
# of echo is implementation defined if the first argument is '-n' or if any
# argument contains a '\', so use printf instead of echo.
printf '%s\n' "VAR=${VAR}"
Questo è un modo conveniente per consentire agli utenti dello script della shell di sovrascrivere un'impostazione senza modificare lo script. (Tuttavia, gli argomenti della riga di comando sono migliori perché non si corre il rischio di comportamenti imprevisti se l'utente ha casualmente la variabile utilizzata nel proprio ambiente esportato.) Ecco come l'utente sovrascriverà l'impostazione:
VAR="other value" ./script
La ${VAR=value}
sintassi dice di impostare VAR
su value
se VAR
non è già impostato, quindi espandere il valore della variabile. Dato che non ci interessa ancora il valore della variabile, viene passato come argomento al comando no-op :
per eliminarlo.
Anche se :
è un comando no-op, l'espansione viene eseguita dalla shell (non dal :
comando!) Prima di eseguire il :
comando in modo che l'assegnazione della variabile si verifichi comunque (se applicabile).
Sarebbe anche accettabile usare true
o qualche altro comando invece di :
, ma il codice diventa più difficile da leggere perché l'intenzione è meno chiara.
Anche il seguente script funzionerebbe:
#!/bin/sh
# print the value of the VAR variable. Note that POSIX says the behavior
# of echo is implementation defined if the first argument is '-n' or if any
# argument contains a '\', so use printf instead of echo.
printf '%s\n' "VAR=${VAR=default value}"
Ma quanto sopra è molto più difficile da mantenere. Se ${VAR}
viene aggiunta una riga che utilizza sopra quella printf
riga, è necessario spostare l'espansione dell'assegnazione predefinita. Se lo sviluppatore dimentica di spostare quell'assegnazione, viene introdotto un bug.
Qualcosa da mettere in un blocco condizionale vuoto
I blocchi condizionali vuoti dovrebbero generalmente essere evitati, ma a volte sono utili:
if some_condition; then
# todo: implement this block of code; for now do nothing.
# the colon below is a no-op to prevent syntax errors
:
fi
Alcune persone sostengono che avere un if
blocco vero vuoto può rendere il codice più facile da leggere che negare il test. Per esempio:
if [ -f foo ] && bar || baz; then
:
else
do_something_here
fi
è probabilmente più facile da leggere di:
if ! [ -f foo ] || ! bar && ! baz; then
do_something_here
fi
Tuttavia credo che ci siano alcuni approcci alternativi che sono migliori di un blocco vero vuoto:
Metti la condizione in una funzione:
exotic_condition() { [ -f foo ] && bar || baz; }
if ! exotic_condition; then
do_something_here
fi
Inserisci la condizione tra parentesi graffe (o parentesi, ma le parentesi generano un processo subshell e tutte le modifiche apportate all'ambiente all'interno della subshell non saranno visibili all'esterno della subshell) prima di annullare:
if ! { [ -f foo ] && bar || baz; } then
do_something_here
fi
Usa ||
invece di if
:
[ -f foo ] && bar || baz || {
do_something_here
}
Preferisco questo approccio quando la reazione è una semplice linea, come affermare le condizioni:
log() { printf '%s\n' "$*"; }
error() { log "ERROR: $*" >&2; }
fatal() { error "$@"; exit 1; }
[ -f foo ] && bar || baz || fatal "condition not met"