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.