So führen Sie eine logische ODER-Verknüpfung in Shell-Skripten durch

571

Ich versuche eine einfache Zustandsprüfung durchzuführen, aber es scheint nicht zu funktionieren.

Wenn $#gleich 0oder größer als ist, 1dann sag hallo.

Ich habe die folgende Syntax ohne Erfolg ausprobiert:

if [ "$#" == 0 -o "$#" > 1 ] ; then
 echo "hello"
fi

if [ "$#" == 0 ] || [ "$#" > 1 ] ; then
 echo "hello"
fi
Erdbeere
quelle
Sie arbeiten beide für mich. Haben Sie eine Shell in der Shebang- Zeile angegeben?
Jason McCreary
1
@ Jason Ich habe die Shebang-Linie tatsächlich vergessen, aber ich habe sie gerade damit getestet und es hat nicht funktioniert.
Erdbeere
25
>ist die Ausgabeumleitung in sh / bash. Jetzt haben Sie wahrscheinlich eine Datei mit dem Namen 1.
Mark4o
Informationen zu Bash-Vergleichen finden Sie hier und hier in meinen Antworten auf frühere Fragen . Weitere Informationen zu Klammern, Doppelklammern und Doppelklammern finden Sie in meiner Antwort hier .
Bis auf weiteres angehalten.
Es funktioniert nicht, weil Sie den Vergleich falsch eingeben: Verwenden Sie "$ #" == "0" oder $ # -eq 0
ETech

Antworten:

987

Das sollte funktionieren:

#!/bin/bash

if [ "$#" -eq 0 ] || [ "$#" -gt 1 ] ; then
    echo "hello"
fi

Ich bin nicht sicher, ob dies in anderen Shells anders ist, aber wenn Sie <,> verwenden möchten, müssen Sie sie wie folgt in doppelte Klammern setzen:

if (("$#" > 1))
 ...
Coding District
quelle
2
Ich bin mir nicht sicher, ob es in einer anderen Shell anders ist, aber in Bash, wenn Sie> oder <verwenden möchten, müssen Sie sie wie folgt in doppelte Klammern setzen: (("$ a" <"$ b"))
Codierung Bezirk
1
@Doug: Es ist nicht so, dass Unix sie nicht verwendet, es ist diese Bash und alle anderen Shells, die ich kenne, verwenden sie für die Eingabe / Ausgabe-Umleitung.
Cascabel
56

Dieser Code funktioniert für mich:

#!/bin/sh

argc=$#
echo $argc
if [ $argc -eq 0 -o $argc -eq 1 ]; then
  echo "foo"
else
  echo "bar"
fi

Ich glaube nicht, dass sh "==" unterstützt. Verwenden Sie "=", um Zeichenfolgen zu vergleichen, und -eq, um Ints zu vergleichen.

man test

für mehr Details.

jbremnant
quelle
Was ist die Option für größer als? Wo ist die offizielle Dokumentation für tihs?
Erdbeere
3
Sollte -gtfür größer sein als. Oder ersetzen Sie einfach alles durch [ $# -ne 1 ].
Mark4o
Größer als -gt, siehe meine Antwort. Die offizielle Dokumentation befindet sich im Man-Test, wie jbremnant hervorgehoben hat.
Coding District
Genau wie ein Fyi für andere, abhängig von Ihrer Shell, unterstützen die meisten == (jetzt ein paar Tage) als Vergleichsoperator, meistens jedoch ist es der gleiche wie der = -Operator. Ich würde mir vorstellen, dass es besser ist, -eq für == oder = zu verwenden, wenn Sie -gt und -ne für Vergleiche verwenden, um Ihren Skriptstil konsistent zu halten. Happy Bashing :)
jkdba
34

Wenn Sie den Bash-Exit-Code Status $ verwenden? Als Variable ist es besser, dies zu tun:

if [ $? -eq 4 -o $? -eq 8 ] ; then  
   echo "..."
fi

Denn wenn Sie dies tun:

if [ $? -eq 4 ] || [ $? -eq 8 ] ; then  

Der linke Teil des OP verändert das $? variabel, also hat der rechte Teil des OP nicht das ursprüngliche $? Wert.

luca76
quelle
2
$ # gibt die Anzahl der an das Skript übergebenen Argumente zurück. Nützlich zur Überprüfung der korrekten Verwendung. Es scheint nicht, dass der Fragesteller Exit-Codes verwendet.
Centimane
27

Manchmal müssen Sie doppelte Klammern verwenden, andernfalls erhalten Sie einen Fehler wie zu viele Argumente

if [[ $OUTMERGE == *"fatal"* ]] || [[ $OUTMERGE == *"Aborting"* ]]
  then
fi
TechNikh
quelle
1
Dies ist nützlich, da ich hier nur ein Beispiel für nicht ganzzahlige Vergleiche sehe, die sich in der Syntax geringfügig unterscheiden.
Christopher Hunter
13

Wenn ein Bash-Skript

If [[ $input -gt number  ||  $input  -lt number  ]]
then 
    echo .........
else
    echo .........

fi

exit
Peprah David
quelle
7

Haben Sie so etwas versucht:

if [ $# -eq 0 ] || [ $# -gt 1 ] 
then
 echo "$#"
fi
John Boker
quelle
Ja, habe ich. Es ist echohallo, auch wenn ich ein einziges Argument habe.
Erdbeere
Der zweite $#könnte der Rückgabewert des ersten Tests sein?
Luckydonald
5

Aus dem Bash-Referenzhandbuch → 3.4.2 Spezielle Parameter

#
($ #) Wird auf die Anzahl der Positionsparameter in Dezimalzahl erweitert.

Daher $#wird immer entweder 0 oder eine größere Ganzzahl sein.

Wenn Sie also etwas tun möchten, wenn $#0 oder größer als 1 ist, müssen Sie nur überprüfen, ob dies der Fall $#ist oder nicht 1:

[ $# -eq 1 ] && echo "1 positional param" || echo "0 or more than 1"

Dies verwendet die Syntax:

[ condition ] && {things if true} || {things if false}
fedorqui 'SO hör auf zu schaden'
quelle
in bash können Sie etwas tun wie:[[ -n $A ]] && echo 1 || echo 2
premek.v
@ premek.v danke für den Kommentar. Meine Antwort wurde sehr schlecht erklärt, ich habe sie nur bearbeitet, in der Hoffnung, dass sie mehr Licht in das Thema bringt.
Fedorqui 'SO hör auf zu schaden'
1

Und in Bash

 line1=`tail -3 /opt/Scripts/wowzaDataSync.log | grep "AmazonHttpClient" | head -1`
 vpid=`ps -ef|  grep wowzaDataSync | grep -v grep  | awk '{print $2}'`
 echo "-------->"${line1}
    if [ -z $line1 ] && [ ! -z $vpid ]
    then
            echo `date --date "NOW" +%Y-%m-%d` `date --date "NOW" +%H:%M:%S` :: 
            "Process Is Working Fine"
    else
            echo `date --date "NOW" +%Y-%m-%d` `date --date "NOW" +%H:%M:%S` :: 
            "Prcess Hanging Due To Exception With PID :"${pid}
   fi

ODER in Bash

line1=`tail -3 /opt/Scripts/wowzaDataSync.log | grep "AmazonHttpClient" | head -1`
vpid=`ps -ef|  grep wowzaDataSync | grep -v grep  | awk '{print $2}'`
echo "-------->"${line1}
   if [ -z $line1 ] || [ ! -z $vpid ]
    then
            echo `date --date "NOW" +%Y-%m-%d` `date --date "NOW" +%H:%M:%S` :: 
            "Process Is Working Fine"
    else
            echo `date --date "NOW" +%Y-%m-%d` `date --date "NOW" +%H:%M:%S` :: 
            "Prcess Hanging Due To Exception With PID :"${pid}
  fi
Ravi Tyagi
quelle