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

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))
 ...

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.


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.


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

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

7

avez-vous essayé quelque chose comme ça:

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

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}

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.