Effizienter Vergleich Wenn Variable existiert und nicht gleich ist

Effizienter Vergleich Wenn Variable existiert und nicht gleich ist

Ich habe ein Problem mit der shSkriptsyntax. 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 OKnur dann wahr sein ( und ausführen ), wenn $StartIPund $OldIPnicht identisch sind. Die Zeile funktioniert, aber ich würde es gerne effizienter sehen. Die Variablen enthalten gültige IP-Adressen.

In einigen Fällen $OldIPwird nichts zugewiesen (nicht initialisiert). Wenn $OldIPes aber nicht existiert, bedeutet das, dass sie in meiner Shell nicht gleich sind!

Ich möchte nicht, dass die Zeile Folgendes ausführt: „if $OldIPdoes not exist -> test if they are different -> run“ echo OK.

Ich möchte, dass die Zeile folgende Bedeutung hat: a) wenn $OldIPnicht vorhanden -> Ende. Plus b) wenn $OldIPvorhanden -> 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 , valuewenn variableer 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 OldIPin vorhanden ist bash, verwenden Sie den -vTest:

 if [[ -v OldIP ]] && [[ "$OldIP" != "$StartIP" ]]; then
     # code
 fi

Dies würde den Stringvergleich zwischen $OldIPund $StartIPnur dann durchführen, wenn OldIPzuvor festgelegt wurde (selbst wenn es auf einen leeren String gesetzt wurde). Beachten Sie, dass der -vTest 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 $varoder 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, messagedass sie nicht $varfestgelegt oder null ist.

Wenn Sie explizit testkompatible Tests benötigen, können Sie Folgendes tun:

[ ! -z "$OldIP" -a "$OldIP" != "$StartIP" ] && echo "OK"

verwandte Informationen