Jak wykonać logiczną operację OR w skryptach powłoki

571

Próbuję wykonać prostą kontrolę stanu, ale wydaje się, że nie działa.

Jeśli $#jest równe 0lub większe niż 1wtedy, przywitaj się.

Wypróbowałem następującą składnię bez powodzenia:

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

if [ "$#" == 0 ] || [ "$#" > 1 ] ; then
 echo "hello"
fi
Truskawka
źródło
Oboje pracują dla mnie. Czy określiłeś powłokę w linii shebang ?
Jason McCreary,
1
@Jason Właściwie to zapomniałem linii shebang, ale właśnie ją przetestowałem i nie zadziałało.
Strawberry
25
>jest przekierowaniem wyjścia w sh / bash. Teraz prawdopodobnie masz plik o nazwie 1.
mark4o
Aby uzyskać informacje na temat porównań Bash, zobacz moje odpowiedzi na poprzednie pytania tutaj i tutaj . Aby uzyskać dodatkowe informacje dotyczące nawiasów, podwójnych nawiasów i podwójnych nawiasów, zobacz moją odpowiedź tutaj .
Wstrzymano do odwołania.
To nie działa, ponieważ błędnie wpisujesz kompromis: użyj „$ #” == „0” lub $ # -eq 0
ETech

Odpowiedzi:

987

To powinno działać:

#!/bin/bash

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

Nie jestem pewien, czy jest inaczej w innych powłokach, ale jeśli chcesz użyć <,>, musisz umieścić je w podwójnym nawiasie, tak jak to:

if (("$#" > 1))
 ...
Dystrykt kodowania
źródło
2
Nie jestem pewien, czy różni się w innej powłoce, ale w bash, jeśli chcesz użyć> lub <, musisz umieścić je w podwójnym nawiasie, tak jak: (("$ a" <"$ b"))
Kodowanie Dystrykt
1
@Doug: To nie tak, że Unix ich nie używa, to ten bash i wszystkie inne powłoki, które znam, używają ich do przekierowywania wejścia / wyjścia.
Cascabel,
56

Ten kod działa dla mnie:

#!/bin/sh

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

Nie sądzę, że sh obsługuje „==”. Użyj „=”, aby porównać ciągi i -eq, aby porównać int.

man test

po więcej szczegółów.

jbremnant
źródło
Jaka jest opcja większego niż? Gdzie jest oficjalna dokumentacja dla tihs?
Strawberry
3
Powinien być -gtwiększy niż. Lub po prostu zamień to wszystko na [ $# -ne 1 ].
mark4o
Większa niż -gt, patrz moja odpowiedź. Oficjalna dokumentacja jest w teście człowieka, jak zauważył jbremnant.
Coding District
Podobnie jak fyi dla innych, w zależności od powłoki, większość obsługuje == (teraz dni) jako operator porównania, jednak przez większość czasu jest taka sama jak operator =. Wyobrażam sobie, że jeśli używasz -gt i -ne do porównań, lepszym rozwiązaniem byłoby użycie -eq dla == lub =, aby zachować spójność stylu skryptowego. Happy Bashing :)
jkdba
34

Jeśli używasz kodu wyjścia bash $? jako zmienna lepiej to zrobić:

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

Ponieważ jeśli to zrobisz:

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

Lewej części OR zmienia $? zmienna, więc w prawej części OR nie ma oryginalnego $? wartość.

luca76
źródło
2
$ # zwraca liczbę argumentów przekazanych do skryptu. Przydatny do sprawdzania poprawności użytkowania. Wygląda na to, że pytający nie używa kodów wyjścia.
Centimane,
27

Czasami trzeba użyć podwójnych nawiasów, w przeciwnym razie pojawia się błąd taki jak zbyt wiele argumentów

if [[ $OUTMERGE == *"fatal"* ]] || [[ $OUTMERGE == *"Aborting"* ]]
  then
fi
TechNikh
źródło
1
Jest to przydatne, ponieważ widzę tu jedyną rzecz, która pokazuje przykład porównań niecałkowitych, które różnią się nieco składnią.
Christopher Hunter
13

Jeśli skrypt bash

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

fi

exit
Peprah David
źródło
7

próbowałeś czegoś takiego:

if [ $# -eq 0 ] || [ $# -gt 1 ] 
then
 echo "$#"
fi
John Boker
źródło
Tak, mam. To echos cześć nawet gdy mam jeden argument.
Strawberry,
Druga $#może być wartością zwracaną z pierwszego testu?
luckydonald
5

Z podręcznika użytkownika Bash → 3.4.2 Parametry specjalne

#
($ #) Rozwija się do liczby parametrów pozycyjnych w systemie dziesiętnym.

Dlatego $#zawsze będzie to 0 lub większa liczba całkowita.

Więc jeśli chcesz coś zrobić, gdy wartość $#jest równa 0 lub większa niż 1, musisz tylko sprawdzić, $#czy jest 1:

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

To używa składni:

[ condition ] && {things if true} || {things if false}
fedorqui „SO przestań szkodzić”
źródło
w bash możesz zrobić coś takiego:[[ -n $A ]] && echo 1 || echo 2
premek.v
@ premek.v dzięki za komentarz. Moja odpowiedź była bardzo źle wyjaśniona, właśnie ją zredagowałem w nadziei, że rzuci więcej światła na ten temat.
fedorqui „SO przestań krzywdzić”
1

I w 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

LUB w 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
źródło