Es gibt zwei Fälle, in denen ich :
nützlich finde :
Standardmäßige Variablenzuweisungen
#!/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}"
Auf diese bequeme Weise können Benutzer Ihres Shell-Skripts eine Einstellung überschreiben, ohne das Skript zu bearbeiten. ( Befehlszeilenargumente sind jedoch besser, da Sie nicht das Risiko eines unerwarteten Verhaltens eingehen, wenn der Benutzer zufällig die Variable hat, die Sie in seiner exportierten Umgebung verwenden.) So würde der Benutzer die Einstellung überschreiben:
VAR="other value" ./script
In der ${VAR=value}
Syntax wird festgelegt, dass auf gesetzt werden soll VAR
, value
wenn dies VAR
noch nicht geschehen ist. Erweitern Sie dann auf den Wert der Variablen. Da uns der Wert der Variablen noch nicht wichtig ist, wird er als Argument an den Befehl no-op übergeben :
, um ihn zu verwerfen.
Obwohl :
es sich um einen No-Op-Befehl handelt, wird die Erweiterung von der Shell ausgeführt (nicht vom :
Befehl!), Bevor der :
Befehl ausgeführt wird, sodass die Variablenzuweisung weiterhin erfolgt (falls zutreffend).
Es wäre auch akzeptabel, true
stattdessen einen oder einen anderen Befehl zu verwenden :
, aber der Code wird schwieriger zu lesen, da die Absicht weniger klar ist.
Das folgende Skript würde auch funktionieren:
#!/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}"
Aber das Obige ist viel schwieriger zu pflegen. Wenn eine Zeile ${VAR}
über dieser printf
Zeile hinzugefügt wird, muss die Standardzuweisungserweiterung verschoben werden. Wenn der Entwickler vergisst, diese Zuweisung zu verschieben, wird ein Fehler gemeldet.
Etwas, das in einen leeren bedingten Block eingefügt werden kann
Leere bedingte Blöcke sollten im Allgemeinen vermieden werden, aber manchmal sind sie nützlich:
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
Einige Leute argumentieren, dass ein leerer True- if
Block das Lesen von Code erleichtern kann, anstatt den Test zu negieren. Beispielsweise:
if [ -f foo ] && bar || baz; then
:
else
do_something_here
fi
ist wohl leichter zu lesen als:
if ! [ -f foo ] || ! bar && ! baz; then
do_something_here
fi
Ich glaube jedoch, dass es einige alternative Ansätze gibt, die besser sind als ein leerer wahrer Block:
Setzen Sie die Bedingung in eine Funktion:
exotic_condition() { [ -f foo ] && bar || baz; }
if ! exotic_condition; then
do_something_here
fi
Setzen Sie die Bedingung in geschweifte Klammern (oder Klammern, aber Klammern rufen einen Subshell-Prozess hervor und alle Änderungen an der Umgebung innerhalb der Subshell sind außerhalb der Subshell nicht sichtbar), bevor Sie negieren:
if ! { [ -f foo ] && bar || baz; } then
do_something_here
fi
Verwenden Sie ||
anstelle von if
:
[ -f foo ] && bar || baz || {
do_something_here
}
Ich bevorzuge diesen Ansatz, wenn es sich bei der Reaktion um eine einfache Einzeilerreaktion handelt, z.
log() { printf '%s\n' "$*"; }
error() { log "ERROR: $*" >&2; }
fatal() { error "$@"; exit 1; }
[ -f foo ] && bar || baz || fatal "condition not met"