Existe alguma grande diferença ao comparar uma variável como uma string ou como um int

21

Por curiosidade, ao fazer uma comparação de variável bash (seu valor sendo um integer ) é possível testá-lo em relação a algum valor predefinido declarado como int ou como string .

Script de amostra :

#!/bin/bash
f1()
{
        [ "$1" == "1" ] && echo "$FUNCNAME: \"1\" compared as string"
}

f2()
{
        [[ "$1" -eq 1 ]] && echo "$FUNCNAME: \"1\" compared as int"
}

f1 $1
f2 $1

Saída :

$  ./param.sh 1
f1: "1" compared as string
f2: "1" compared as int

e

$  ./param.sh blah
$

Ambas as funções se comportam da mesma maneira, e por isso estou querendo saber se há uma maneira preferida ao verificar uma variável inteira? Eu iria para verificar int versus int como é mais rigoroso, mas eu me pergunto se há algum inconveniente fazendo com string

Nesse caso, f2() também é mais rigoroso em relação à comparação, ou seja, a passagem de um valor decimal o quebrará, enquanto f1() não terá problemas.

    
por fduff 10.07.2014 / 16:26

3 respostas

18

Sim, muitas diferenças. Por exemplo, = verifica a igualdade exata da cadeia de caracteres, mas -eq avalia aritmeticamente ambas as expressões antes de verificar a igualdade:

$ [ " 1 " -eq 1 ] && echo equal || echo not
equal
$ [ " 1 " = 1 ] && echo equal || echo not
not

$ [ +1 -eq 1 ] && echo equal || echo not
equal
$ [ +1 = 1 ] && echo equal || echo not
not

$ [ "0+1" -eq 1 ] && echo equal || echo not
equal
$ [ "0+1" = 1 ] && echo equal || echo not
not

Além disso, a string vazia é numericamente igual a zero:

$ [ "" -eq 0 ] && echo equal || echo not
equal
$ [ "" = 0 ] && echo equal || echo not
not

E toda uma outra classe de diferenças aparece quando você coloca os operadores de comparação - considerando < vs -lt , por exemplo:

$ [[ 2 -lt 10 ]] && echo less || echo not
less
$ [[ 2 < 10 ]] && echo less || echo not
not

Isso ocorre porque a string "2" está em ordem alfabética após a string "10" (já que 1 vem antes de 2), mas o número "2" é numericamente menor que o número "10".

    
por 10.07.2014 / 16:48
7

A comparação entre inteiros e sequências de caracteres se torna mais significativa quando você está comparando maior ou menor que:

#!/bin/bash

eleven=11
nine=9

[[ $nine < $eleven ]] && echo string   # fail

[[ "$nine" -lt "$eleven" ]] && echo integer # pass

O primeiro falha porque 9 vem depois de 11 quando classificado lexicograficamente.

Observe que o uso de aspas não determina se você está comparando strings ou números, o operador o faz. Você pode adicionar ou remover as citações acima, isso não faz nenhuma diferença. Bash pega variáveis indefinidas entre parênteses duplos, então aspas não são necessárias. Usar aspas com colchetes únicos para testes numéricos não o salvará desde:

[ "" -lt 11 ]

é um erro de qualquer forma ("expressão inteira requerida"). As cotações são uma proteção eficaz com comparações de caracteres em colchetes individuais:

[ "" \< 11 ]

Anote os colchetes duplos , "" -eq 0 mas não == 0 .

    
por 10.07.2014 / 16:46
2

Além do que foi dito.
Comparar por igualdade é mais rápido com números, embora em scripts de shell seja raro precisar de cálculos rápidos.

$ b=234
$ time for ((a=1;a<1000000;a++)); do [[ $b = "234" ]]; done

real    0m13.008s
user    0m12.677s
sys 0m0.312s

$ time for ((a=1;a<1000000;a++)); do [[ $b -eq 234 ]]; done

real    0m10.266s
user    0m9.657s
sys 0m0.572s
    
por 10.07.2014 / 17:22

Tags