Comment faire une opération OU logique dans un script shell

571

J'essaie de faire une simple vérification de l'état, mais cela ne semble pas fonctionner.

Si $#est égal 0ou supérieur à 1alors dites bonjour.

J'ai essayé la syntaxe suivante sans succès:

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

if [ "$#" == 0 ] || [ "$#" > 1 ] ; then
 echo "hello"
fi
fraise
la source
Ils travaillent tous les deux pour moi. Avez-vous spécifié une coquille dans la ligne shebang ?
Jason McCreary
1
@Jason J'ai en fait oublié la ligne shebang, mais je l'ai testée avec elle tout à l'heure et cela n'a pas fonctionné.
Fraise
25
>est la redirection de sortie en sh / bash. Maintenant, vous avez probablement un fichier nommé 1.
mark4o
Pour plus d'informations sur les comparaisons Bash, veuillez consulter mes réponses aux questions précédentes ici et ici . Pour plus d'informations sur les crochets, les crochets doubles et les doubles parenthèses, voir ma réponse ici .
pause jusqu'à nouvel ordre.
Cela ne fonctionne pas car vous avez mal tapé la compilation: utilisez "$ #" == "0" ou $ # -eq 0
ETech

Réponses:

987

Cela devrait fonctionner:

#!/bin/bash

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

Je ne sais pas si c'est différent dans d'autres shells mais si vous souhaitez utiliser <,>, vous devez les mettre entre parenthèses doubles comme ceci:

if (("$#" > 1))
 ...
District de codage
la source
2
Je ne sais pas si c'est différent dans un autre shell mais en bash, si vous souhaitez utiliser> ou <, vous devez les mettre entre parenthèses double comme ceci: (("$ a" <"$ b"))
Codage District
1
@Doug: Ce n'est pas qu'Unix ne les utilise pas, c'est que bash et tous les autres shells que je connais les utilisent pour la redirection d'entrée / sortie.
Cascabel
56

Ce code fonctionne pour moi:

#!/bin/sh

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

Je ne pense pas que sh supporte "==". Utilisez "=" pour comparer les chaînes et -eq pour comparer les entiers.

man test

pour plus de détails.

jbremnant
la source
Quelle est l'option pour plus de? Où est la documentation officielle des tihs?
Strawberry
3
Doit être -gtsupérieur à. Ou remplacez tout simplement par [ $# -ne 1 ].
mark4o
Plus grand que -gt, voir ma réponse. La documentation officielle est en test, comme l'a souligné jbremnant.
Coding District
Tout comme un fyi pour les autres, en fonction de votre shell, la plupart prennent en charge == (maintenant quelques jours) comme opérateur de comparaison, mais la plupart du temps, c'est la même chose que l'opérateur =. J'imagine que si vous utilisez -gt et -ne pour les comparaisons, il serait préférable d'utiliser -eq pour == ou = pour garder votre style de script cohérent. Happy Bashing :)
jkdba
34

Si vous utilisez l'état de code de sortie bash $? comme variable, il vaut mieux faire ceci:

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

Parce que si vous le faites:

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

La partie gauche du OU modifie le $? variable, donc la partie droite du OU n'a pas le $? valeur.

luca76
la source
2
$ # renvoie le nombre d'arguments transmis au script. Utile pour vérifier l'utilisation correcte. Il ne semble pas que le demandeur utilise des codes de sortie.
Centimane
27

Parfois, vous devez utiliser des crochets doubles, sinon vous obtenez une erreur comme trop d'arguments

if [[ $OUTMERGE == *"fatal"* ]] || [[ $OUTMERGE == *"Aborting"* ]]
  then
fi
TechNikh
la source
1
C'est utile parce que c'est la seule chose ici que je vois montrant un exemple de comparaisons non entières, qui sont légèrement différentes dans la syntaxe.
Christopher Hunter
13

Si un script bash

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

fi

exit
Peprah David
la source
7

avez-vous essayé quelque chose comme ça:

if [ $# -eq 0 ] || [ $# -gt 1 ] 
then
 echo "$#"
fi
John Boker
la source
Oui j'ai. C echoest bon même quand j ai un seul argument.
Strawberry
La seconde $#pourrait être la valeur de retour du premier test?
luckydonald
5

Depuis le manuel de référence de Bash → 3.4.2 Paramètres spéciaux

#
($ #) Se développe en nombre de paramètres positionnels en décimal.

Donc, $# sera toujours 0 ou un entier plus grand.

Donc, si vous voulez faire quelque chose à partir de $#0 ou de plus de 1, il vous suffit de vérifier si $#oui ou non 1:

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

Cela utilise la syntaxe:

[ condition ] && {things if true} || {things if false}
fedorqui 'SO arrête de nuire'
la source
en bash, vous pouvez faire quelque chose comme:[[ -n $A ]] && echo 1 || echo 2
premek.v
@ premek.v merci pour le commentaire. Ma réponse était très mal expliquée, je viens de la modifier dans l'espoir qu'elle éclaircisse le sujet.
fedorqui 'SO arrête de nuire'
1

Et dans 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

OU dans 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
la source