Como executar uma operação OR lógica em scripts de shell

571

Estou tentando fazer uma verificação simples da condição, mas parece não funcionar.

Se $#for igual 0ou superior a, 1então diga olá.

Eu tentei a seguinte sintaxe sem êxito:

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

if [ "$#" == 0 ] || [ "$#" > 1 ] ; then
 echo "hello"
fi
morango
fonte
Ambos trabalham para mim. Você especificou um shell na linha shebang ?
Jason McCreary
1
@ Jason: Na verdade, esqueci a linha shebang, mas testei com ela agora e não funcionou.
Strawberry
25
>é o redirecionamento de saída em sh / bash. Agora você provavelmente tem um arquivo chamado 1.
mark4o
Para obter informações sobre comparações do Bash, consulte minhas respostas às perguntas anteriores aqui e aqui . Para obter informações adicionais sobre colchetes, colchetes duplos e parênteses duplos, consulte minha resposta aqui .
Pausado até novo aviso.
Não funciona porque você digitou incorretamente a composição: use "$ #" == "0" ou $ # -eq 0
ETech

Respostas:

987

Isso deve funcionar:

#!/bin/bash

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

Não tenho certeza se isso é diferente em outros shells, mas se você deseja usar <,>, é necessário colocá-los entre parênteses duplos da seguinte forma:

if (("$#" > 1))
 ...
Coding District
fonte
2
Não tenho certeza se é diferente em outro shell, mas no bash, se você deseja usar> ou <, você deve colocá-los entre parênteses assim: (("$ a" <"$ b"))
Codificação distrito
1
@ Doug: Não é que o unix não os use, é que o bash e todos os outros shells que conheço os usam para redirecionamento de entrada / saída.
Cascabel
56

Este código funciona para mim:

#!/bin/sh

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

Eu não acho que sh suporte "==". Use "=" para comparar strings e -eq para comparar ints.

man test

para mais detalhes.

jbremnant
fonte
Qual é a opção para maior que? Onde está a documentação oficial para você?
Strawberry
3
Deve ser -gtmaior que. Ou apenas substitua tudo por [ $# -ne 1 ].
mark4o
Maior que é -gt, veja minha resposta. A documentação oficial está em teste de homem, como o jbremnant apontou.
Coding District
Assim como um fyi para outros, dependendo do seu shell, a maioria suporta == (agora por dia) como um operador de comparação, no entanto, na maioria das vezes, é o mesmo que o operador =. Eu imagino que, se você estiver usando -gt e -ne para comparações, seria melhor usar -eq para == ou = para manter seu estilo de script consistente. Feliz Bashing :)
jkdba
34

Se você estiver usando o status do código de saída do bash $? como variável, é melhor fazer isso:

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

Porque se você fizer:

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

A parte esquerda do OR altera o $? variável, para que a parte correta do OR não tenha o $ original ? valor.

luca76
fonte
2
$ # retorna o número de argumentos passados ​​para o script. Útil para verificar o uso correto. Não parece que o solicitante está usando códigos de saída.
Centimane
27

Às vezes, você precisa usar colchetes duplos, caso contrário, você recebe um erro como muitos argumentos

if [[ $OUTMERGE == *"fatal"* ]] || [[ $OUTMERGE == *"Aborting"* ]]
  then
fi
TechNikh
fonte
1
Isso é útil porque é a única coisa aqui que vejo mostrando um exemplo de comparações não inteiras, que são ligeiramente diferentes na sintaxe.
22619 Christopher Hunter
13

Se um script bash

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

fi

exit
Peprah David
fonte
7

você já tentou algo assim:

if [ $# -eq 0 ] || [ $# -gt 1 ] 
then
 echo "$#"
fi
John Boker
fonte
Sim, eu tenho. É echoum alô mesmo quando tenho um único argumento.
Strawberry
O segundo $#pode ser o valor de retorno do primeiro teste?
luckydonald 17/06/19
5

No Manual de Referência do Bash → 3.4.2 Parâmetros especiais

#
($ #) Expande para o número de parâmetros posicionais em decimal.

Portanto, $#sempre será 0 ou um número inteiro maior.

Portanto, se você deseja fazer algo sempre $#que 0 ou maior que 1, basta verificar se $#é ou não 1:

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

Isso usa a sintaxe:

[ condition ] && {things if true} || {things if false}
fedorqui 'Então pare de prejudicar'
fonte
no bash você pode fazer algo como:[[ -n $A ]] && echo 1 || echo 2
premek.v 16/01/17
@ premek.v obrigado pelo comentário. Minha resposta foi muito mal explicada, eu apenas a editei na esperança de esclarecer mais o assunto.
fedorqui 'Então, pare de prejudicar'
1

E no 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 no 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
fonte