BASH: Operador OR para $ 1 posicional

0

Eu enfrentei um problema, em que o operador OR não trabalha por US $ 1. Por exemplo:

if [[ "$1" != '1' || '2' ]]
        then
               echo "BAD"
        else
               echo "OK"
        fi

Quando executo este teste, não importa o que seja $ 1, sempre aparece BAD.

Como posso vincular $ 1 a apenas 1 ou 2?

    
por faceless 08.02.2018 / 12:52

4 respostas

5

Com a sintaxe sh padrão (portanto, não apenas reconhecida por bash , mas todas as outras shells compatíveis com POSIX):

case $1 in
  (1 | 2) echo OK;;
  (*) echo BAD;;
esac

Ou:

if [ "$1" = 1 ] || [ "$1" = 2 ]; then
  echo OK
else
  echo BAD
fi

(note que é uma comparação byte a byte de strings. 01, 1e0, 1.0, 20/20, 0x1 também seria considerado como BAD, embora numericamente eles possam ser considerados como sendo iguais a 1 ) .

Observe que os operadores = / != na construção bash [[...]] (copiados de ksh ) são na verdade operadores de correspondência de padrões, em oposição aos operadores de igualdade, portanto, neste caso especial em que você deseja Para corresponder a um único caractere, você também pode usar [[ $1 != [12] ]] como você poderia fazer case $1 in ([12]) na sintaxe sh padrão.

    
por 08.02.2018 / 13:12
4

O motivo pelo qual você sempre entra na ramificação BAD da instrução if é que o teste

[[ "$1" != '1' || '2' ]]

primeiro testa se $1 não é 1 e, se não for, BAD é impresso. Se for, 2 é avaliado como um teste. Uma string como 2 é sempre true e BAD é impressa.

Em vez disso:

if [ "$1" != '1' ] && [ "$1" != '2' ]; then

ou, com testes aritméticos,

if [ "$1" -ne 1 ] && [ "$1" -ne 2 ]; then

ou, usando avaliação aritmética,

if (( $1 != 1 )) && (( $1 != 2 )); then
    
por 08.02.2018 / 13:02
1
if [[ "$1" != '1' || "$1" != '2' ]]
then
               echo "BAD"
else
               echo "OK"
fi

Em seguida, a instrução! = precisa ser repetida para o diferente de 2, assim como 1

    
por 08.02.2018 / 12:56
1

A lógica de ($1 != 1) OR ($1 != 2) é falha.

Se $1 for 1 , então não será igual a 2 , então o teste será verdadeiro.
Além disso, se $1 for 2 , então, não é igual a 1 , então o teste também será verdadeiro. Em suma, o teste será sempre verdadeiro.

Você deve testar a igualdade: ($1 == 1) or ($1 == 2) assim:

if [[ ($1 == '1') || ($1 == '2') ]]; then
    echo "$1 OK"
else
    echo "$1 BAD"
fi

Ou mais simples (em ksh, bash ou zsh):

[[ $1 == [12] ]] && echo "$1 OK" || echo "$1 BAD"

Ou usando a sintaxe sh (portável para todos os shells do POSIX):

if [ "$1" = '1' ] || [ "$1" = '2' ]; then
            echo "$1 OK"
else
            echo "$1 BAD"
fi

Ou com um idioma de caso:

case $1 in
    (1 | 2) echo "$1 OK"  ;;
    (*) echo BAD "$1 BAD" ;;
esac

Todos os itens acima são uma comparação de string, se você quiser uma comparação numérica, você pode fazer:

if [ "$1" -eq 1 ] || [ "$1" -eq 2 ]; then
            echo "$1 OK"
else
            echo "$1 BAD"
fi

No entanto, isso não funcionará se $1 for 1.0 ou 1e0 ou muitos outros equivalentes numéricos a 1 . Trabalhará com 01 ou 0001 embora.

    
por 08.02.2018 / 20:02

Tags