2017-01-12 9 views
0

Ich denke, mytrue und myfalse werden als Zeichenfolge statt Befehle:Bash: wie Ergebnisse von Befehlen in doppelten eckigen Klammern bewerten

myfalse() { 
    return 0 
} 

mytrue() { 
    return 1 
} 

test-conditional () { 
    SHOW="dont-show" 
    [[ ${SHOW} == "show" || mytrue ]] && echo "ok" || echo "wrong" 
    [[ ${SHOW} == "show" && mytrue ]] && echo "err" || echo "ok" 
    [[ ${SHOW} == "show" || myfalse ]] && echo "err" || echo "ok" 
    [[ ${SHOW} == "show" && myfalse ]] && echo "err" || echo "ok" 
    SHOW="show" 
    [[ ${SHOW} == "show" || mytrue ]] && echo "ok" || echo "err" 
    [[ ${SHOW} == "show" && mytrue ]] && echo "ok" || echo "err" 
    [[ ${SHOW} == "show" || myfalse ]] && echo "ok" || echo "err" 
    [[ ${SHOW} == "show" && mytrue ]] && echo "err" || echo "ok" 

} 

test-conditional 

So wird diese falsche Ausgabe zeigen:

ok 
ok 
err 
ok 
ok 
ok 
ok 
err 

(Es soll sein ok überall)

Wie können Befehle in doppelten eckigen Klammern auswerten?

+0

Sie nicht, nur die Klammern entfernen. oder schließe nur den '==' Vergleich innen ein, d.h '[[$ {SHOW} ==" show "]] || mytrue' – 123

+0

Auch 0 ist in bash wahr. – 123

Antwort

4

Sie haben true und false Funktionen, die entgegengesetzte Rückkehrcodes zurückgeben, und Ihre letzte Bedingung benötigt eine Korrektur.

können Sie verwenden:

myfalse() { 
    return 1 
} 

mytrue() { 
    return 0 
} 

test-conditional () { 
    SHOW="dont-show" 
    [[ ${SHOW} == "show" ]] || mytrue && echo "ok" || echo "wrong" 
    [[ ${SHOW} == "show" ]] && mytrue && echo "err" || echo "ok" 
    [[ ${SHOW} == "show" ]] || myfalse && echo "err" || echo "ok" 
    [[ ${SHOW} == "show" ]] && myfalse && echo "err" || echo "ok" 
    SHOW="show" 
    [[ ${SHOW} == "show" ]] || mytrue && echo "ok" || echo "err" 
    [[ ${SHOW} == "show" ]] && mytrue && echo "ok" || echo "err" 
    [[ ${SHOW} == "show" ]] || myfalse && echo "ok" || echo "err" 
    [[ ${SHOW} == "show" ]] && myfalse && echo "err" || echo "ok" 
} 

test-conditional 

Beachten Sie auch, wie Funktionsaufruf sonst außerhalb [[ ... ]] platziert wird Funktion nicht aufrufen wird.

gelten folgende Regeln während diese Ausdrücke Bewertung:

  1. Zustand nach && wird nicht ausgewertet, wenn der erste Zustand ausfällt.
  2. Bedingung nach || wird nicht ausgewertet, wenn die erste Bedingung erfolgreich ist.
+0

Danke. Können Sie erklären, wie diese logischen Ausdrücke bewertet werden? Was sind die Vorrangregeln? Werden mytrue/myfalse immer genannt? Ich vermute nicht, weil Echo nicht immer aufgerufen wird. Wie funktioniert das genau? – dangonfast

+0

Dies sind logische Standardprogrammierkonstrukte. 1. Bedingung nach '&&' wird nicht ausgewertet, wenn die erste Bedingung fehlschlägt. 2. Bedingung nach '||' wird nicht ausgewertet, wenn die erste Bedingung erfolgreich ist. – anubhava

+0

Und '&&' hat Vorrang vor '||'? Das ist: 'a && b || c bedeutet '(a && b) || c' und 'a || b && c 'bedeutet "a || (b && c) '? Es ist verwirrend, weil die && Operatoren in bash leicht unterschiedliche Dinge innerhalb und außerhalb von Klammern zu tun scheinen (wahrscheinlich nicht bei doppelten Klammern) – dangonfast

1

Innerhalb eines bash [[…]] (und innerhalb der älteren […] in den meisten Shells), was zählt, ist, wenn der getestete Wert einige Zeichen hat oder nicht:

$ [[ somevalue ]] && echo "yes" || echo "no" 

Wenn der Wert leer getestet, wenn der Test nicht bestanden :

$ [[ "" ]] && echo "yes" || echo "no" 
no 

Das gilt auch für Variablen ist:

$ somevalue="a false string" 
$ [[ $somevalue ]] && echo "yes" || echo "no" 
yes 

$ somevalue="" 
$ [[ $somevalue ]] && echo "yes" || echo "no" 
no 

Also, [[…]] ist beschränkt auf Testzeichenfolgen nicht "Exit-Codes".
Ihre Funktionen definieren "Exit-Codes", keine Zeichenfolgen.
Sie können definieren

  1. die Werte von mytrue und myfalse Variablen sein, die diese Werte darstellen:

    mytrue=A_True_Value 
    myfalse="" 
    

    und nutzen sie:

    $ show="dont-show" 
    $ [[ ${SHOW} == "show" || $mytrue ]] && echo "ok" || echo "wrong" 
    ok 
    
    $ [[ ${SHOW} == "show" || $myfalse ]] && echo "ok" || echo "wrong" 
    wrong 
    
  2. Oder eigentlich Ausfahrt Test Codes außerhalb eines [[…]] Idioms:

    $ mytrue(){ return 0; } 
    $ if mytrue; then echo "ok"; else echo "wrong"; fi 
    ok 
    
    $ mytrue && echo "ok" || echo "wrong" 
    ok 
    
  3. One (komplexere) Alternative ist, die Funktionen Wert emittieren zu machen und die Ausführung des Codes in den Funktionen des [[…]] Idiom nennen:

    $ mytrue(){ echo "A_True_Value"; } 
    $ myfalse(){ echo ""; } 
    $ show="dont-show" 
    $ [[ ${SHOW} == "show" || $(mytrue) ]] && echo "ok" || echo "wrong" 
    ok 
    

KISS

aber (wahrscheinlich) die einfachsten Lösungen ist die beste Lösung:

myfalse="" 
mytrue="true" 

test-conditional() { 
    show="dont-show" 
    [[ ${show} == "show" || $mytrue ]] && echo "ok" || echo "wrong" 
    [[ ${show} == "show" && $mytrue ]] && echo "err" || echo "ok" 
    [[ ${show} == "show" || $myfalse ]] && echo "err" || echo "ok" 
    [[ ${show} == "show" && $myfalse ]] && echo "err" || echo "ok" 
    show="show" 
    [[ ${show} == "show" || $mytrue ]] && echo "ok" || echo "err" 
    [[ ${show} == "show" && $mytrue ]] && echo "ok" || echo "err" 
    [[ ${show} == "show" || $myfalse ]] && echo "ok" || echo "err" 
    [[ ${show} == "show" && $myfalse ]] && echo "err" || echo "ok" 
} 

test-conditional 
+0

tatsächlich sind mytrue und myfalse keine Konstanten: Ich benutze das, um eine' check' Funktion zu simulieren, die 1 für false und 0 für true zurückgeben kann (ich benutzte die falschen Rückgabewerte in meiner ursprünglichen Frage). Das heißt, ich mag die Einfachheit des letzten Abschnitts in Ihrer Antwort: wie kann ich das tun, stellen Sie sicher, dass: 1) die 'check' Funktion aufgerufen wird 2) der Rückgabewert überprüft wird, nicht der ausgegebene Text – dangonfast

+0

In einem [ [...]] Sie können nur einen Text (Variable) oder die Ausgabe eines Befehls (Funktion/Alias) testen. Wenn Sie die Bedingung "Nicht der ausgegebene Text" festlegen, dann lehnen Sie die "Ausgabe eines Befehls" ab. Die einzige Möglichkeit, einen Test durchzuführen, besteht darin, eine Variable zu verwenden. Das ist die Lösung, die ich geschrieben habe. (Forts.) – sorontar

+0

Die einzige andere Alternative besteht darin, die Tests außerhalb von [[...]] durchzuführen. Dies wurde von anderen Benutzern bereitgestellt, indem ein UND-ODER-Verbundbefehl erstellt wurde. Ich kann mir keinen Weg vorstellen, Code auszuführen und auf einen Wert zu testen (das ist kein "emited text"), nicht einmal mit arithmetischen Erweiterungen. Scheint mir, dass Ihre Anforderungen alle gleichzeitig erfüllt werden können. (Forts.) – sorontar

Verwandte Themen