Przydają mi się dwa przypadki :
:
Domyślne przypisania zmiennych
#!/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}"
Jest to wygodny sposób na zezwolenie użytkownikom skryptu powłoki na zastąpienie ustawienia bez edytowania skryptu. (Jednak argumenty wiersza polecenia są lepsze, ponieważ nie ryzykujesz nieoczekiwanym zachowaniem, jeśli użytkownik przypadkowo ma zmienną, której używasz w wyeksportowanym środowisku). Oto, w jaki sposób użytkownik zastąpi to ustawienie:
VAR="other value" ./script
${VAR=value}
Składnia mówi do zestawu VAR
, aby value
jeśli VAR
nie jest już ustawiony, a następnie rozszerzyć do wartości zmiennej. Ponieważ nie zależy nam jeszcze na wartości zmiennej, jest ona przekazywana jako argument do polecenia no-op, :
aby ją wyrzucić.
Mimo że polecenie :
to nie działa, interpretacja jest wykonywana przez powłokę (nie :
polecenie!) Przed uruchomieniem :
polecenia, więc przypisanie zmiennej nadal występuje (jeśli dotyczy).
Dopuszczalne byłoby również użycie true
lub użycie innego polecenia :
, ale kod staje się trudniejszy do odczytania, ponieważ zamiar jest mniej jasny.
Działa również następujący skrypt:
#!/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}"
Ale powyższe jest znacznie trudniejsze do utrzymania. Jeśli ${VAR}
powyżej linii zostanie dodana linia używająca, printf
należy przenieść domyślne rozszerzenie przypisania. Jeśli programista zapomni przenieść to zadanie, zostanie wprowadzony błąd.
Coś do umieszczenia w pustym bloku warunkowym
Ogólnie należy unikać pustych bloków warunkowych, ale czasem są one przydatne:
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
Niektórzy twierdzą, że posiadanie pustego prawdziwego if
bloku może ułatwić odczytanie kodu niż negowanie testu. Na przykład:
if [ -f foo ] && bar || baz; then
:
else
do_something_here
fi
jest prawdopodobnie łatwiejszy do odczytania niż:
if ! [ -f foo ] || ! bar && ! baz; then
do_something_here
fi
Jednak uważam, że istnieje kilka alternatywnych metod, które są lepsze niż pusty prawdziwy blok:
Umieść warunek w funkcji:
exotic_condition() { [ -f foo ] && bar || baz; }
if ! exotic_condition; then
do_something_here
fi
Umieść warunek w nawiasach klamrowych (lub nawiasach, ale nawiasy spawnują proces podpowłoki, a wszelkie zmiany dokonane w środowisku w podpowłoce nie będą widoczne poza podpowłoką) przed zanegowaniem:
if ! { [ -f foo ] && bar || baz; } then
do_something_here
fi
Użyj ||
zamiast if
:
[ -f foo ] && bar || baz || {
do_something_here
}
Wolę to podejście, gdy reakcja jest prostą jednowarstwową, taką jak zapewnienie warunków:
log() { printf '%s\n' "$*"; }
error() { log "ERROR: $*" >&2; }
fatal() { error "$@"; exit 1; }
[ -f foo ] && bar || baz || fatal "condition not met"