Ich habe ein Problem mit der sh
Skriptsyntax. Ich habe ein Skript für meinen Asus-Router geschrieben. Das Skript funktioniert einwandfrei. Aber ich habe diese Zeile:
if [[ "$OldIP" && "$StartIP" != "$OldIP" ]]; then echo OK; fi
Es sollte echo OK
nur dann wahr sein ( und ausführen ), wenn $StartIP
und $OldIP
nicht identisch sind. Die Zeile funktioniert, aber ich würde es gerne effizienter sehen. Die Variablen enthalten gültige IP-Adressen.
In einigen Fällen $OldIP
wird nichts zugewiesen (nicht initialisiert). Wenn $OldIP
es aber nicht existiert, bedeutet das, dass sie in meiner Shell nicht gleich sind!
Ich möchte nicht, dass die Zeile Folgendes ausführt: „if $OldIP
does not exist -> test if they are different -> run“ echo OK
.
Ich möchte, dass die Zeile folgende Bedeutung hat: a) wenn $OldIP
nicht vorhanden -> Ende. Plus b) wenn $OldIP
vorhanden -> testen, ob sie unterschiedlich sind -> ausführen echo OK
.
Also, ich würde es, wenn möglich, gerne "$OLDIP" &&
irgendwie entfernen. Kein wirkliches Problem; bin gespannt, mehr zu erfahren :)
Irgendwie schon (funktioniert aber nicht):
if [ [ "$OldIP" ] != "$StartIP" ]; then echo OK; fi
oder
if [ $OldIP != "$StartIP" ]; then echo OK; fi
das macht was ich will, aber meckert, wennAlteIPist leer (funktioniert aber einwandfrei)
während
if [ "$OldIP" != "$StartIP" ]; then echo OK; fi
funktioniert, ignoriert aber dasAlteIPist leer
Antwort1
Streng genommen existiert eine Variable nicht, wenn ihr nie ein Wert zugewiesen wurde oder wenn ihr ein Wert zugewiesen wurde unset
. Eine Variable mit einem leeren String als Wertexistiert.
Die Standardparametererweiterung ${variable+value}
ersetzt den String , value
wenn variable
er existiert (nicht nicht gesetzt oder leer ist). Dies könnte verwendet werden, um die Existenz wie folgt zu testen:
if [ "${OldIP+x}" = "x" ] && [ "$OldIP" != "$StartIP" ]; then
# code
fi
Um zu testen, ob OldIP
in vorhanden ist bash
, verwenden Sie den -v
Test:
if [[ -v OldIP ]] && [[ "$OldIP" != "$StartIP" ]]; then
# code
fi
Dies würde den Stringvergleich zwischen $OldIP
und $StartIP
nur dann durchführen, wenn OldIP
zuvor festgelegt wurde (selbst wenn es auf einen leeren String gesetzt wurde). Beachten Sie, dass der -v
Test dieNameder Variablen.
Antwort2
Ich denke, Ihr Skript ist so, wie es ist, ziemlich effizient. Sie verbringen sicherlich nicht viele Zyklen damit.
Eine andere Möglichkeit, die Logik zu schreiben:
{ test -n "$OldIP" || test "$StartIP" != "$OldIP"; } && echo OK
Hier steht: „Wenn OldIP gesetzt ist oder wenn OldIP und StartIP unterschiedlich sind, dann echo OK.“
Denken Sie daran, dass es [
sich hierbei um einen anderen Namen handelt, über test(1)
den Sie mit mehr erfahren können man 1 test
.
Bearbeiten: Achten Sie wie Gilles betont hat darauf, die Erstellung von Untershells zu vermeiden ( ... )
, wo sie nicht benötigt werden.
{ ... ; }
kann verwendet werden, um Befehle zu gruppieren, ohne eine neue Shell auszuführen.
Kurzreferenz:http://www.gnu.org/software/bash/manual/html_node/Command-Grouping.html
Antwort3
Dies macht, was Sie verlangen:
[ "${OldIP:-"$StartIP"}" != "$StartIP" ] && echo "OK"
Wie auch dies (komplexer):
${OldIP:+false} || { [[ $OldIP != $StartIP ]] && echo "OK"; }
Antwort4
Wenn Sie verwenden bash
, können Sie eine Standardsubstitution verwenden:
[[ "${OldIP:=oldunset}" != "${StartIP?StartUnset" ]] && echo "OK"
Die Syntax ${var:-def}
wird entweder als aktueller Wert von $var
oder als angegebener Standardwert (in diesem Fall def
) ausgewertet, wenn die Variable nicht gesetzt oder null ist. Der Wert der Variablen (sofern vorhanden) bleibt unverändert.
Die Syntax ${var?message}
wird mit einem Fehlercode von 1 und der Meldung beendet, message
dass sie nicht $var
festgelegt oder null ist.
Wenn Sie explizit test
kompatible Tests benötigen, können Sie Folgendes tun:
[ ! -z "$OldIP" -a "$OldIP" != "$StartIP" ] && echo "OK"