Qual é a diferença entre os sinais de igual simples e duplo (=) nas comparações shell?

19

Leia que para comparar strings dentro de if , precisamos usar colchetes duplos. Alguns livros dizem que a comparação pode ser feita por = . Mas funciona com o == também.

#!/bin/bash
a="hello"
b="world"
if [[ $a == $b ]];then
    echo "equal"
fi

Existe uma diferença entre = e == na comparação?

    
por user3539 11.04.2013 / 07:27

2 respostas

23

[[ $a == $b ]] não é comparação, é correspondência de padrões. Você precisa de [[ $a == "$b" ]] para comparação de igualdade de byte a byte. = é o mesmo que == em qualquer shell que suporte [[...]] (introduzido por ksh ).

[[...]] não é a sintaxe sh padrão. O comando [ é padrão, e o operador padrão comparação é = (embora algumas implementações [ também reconheçam == ).

Assim como em qualquer argumento para qualquer comando, as variáveis devem ser citadas, então:

[ "$a" = "$b" ]

No padrão sh , a correspondência de padrões é feita com case :

case $a in
  ($b) ...
esac

Para completar, outros operadores parecidos com a igualdade que você pode encontrar em shell scripts:

  • [ "$a" -eq "$b" ] : operador [ padrão para comparar números inteiros decimais. Algumas implementações [ permitem espaços em branco em torno dos números, alguns permitem expressões aritméticas arbitrárias, mas isso não é portátil. Portavelmente, pode-se usar [ "$((a))" -eq "$((b))" ] para isso. Veja também [ "$((a == b))" -ne 0 ] , que seria o equivalente padrão (exceto que POSIXly, o comportamento é especificado apenas se $a e $b contiverem constantes inteiras) de:
  • ((a == b)) , de ksh e também encontrado em zsh e bash , retorna verdadeiro se a avaliação da expressão aritmética armazenada em $a gerar o mesmo número que a de $b . Normalmente, isso é usado para comparar números. Note que existem variações entre shells e como expressões aritméticas são avaliadas e quais números são suportados (por exemplo, bash e algumas implementações / versões de ksh não suportam ponto flutuante ou tratam números com zeros à esquerda como octal).

  • expr "$a" = "$b" faz uma comparação numérica se ambos os operandos forem reconhecidos como números inteiros decimais (alguns permitindo espaços em branco ao redor do número) e, de outra forma, verifica se os dois operadores de cadeia possuem a mesma ordem de classificação. Também falharia os valores de $a ou $b que são expr de operadores como ( , substr ...

  • awk 'BEGIN{exit !(ARGV[1] == ARGV[2])}' "$a" "$b" : se $a e $b forem reconhecidos como números (pelo menos números inteiros decimais e de ponto flutuante como 1.2, -1.5e-4, espaços em branco à esquerda ignorados, alguns também reconhecendo hexadecimais, octal ou qualquer coisa reconhecida por strtod() ), então uma comparação numérica é executada. Caso contrário, dependendo da implementação, é uma comparação de cadeia de byte a byte ou semelhante à comparação expr a strcoll() , isto é, se $a e $b ordenam o mesmo.

Veja também:

por 11.04.2013 / 08:37
11

Estes são equivalentes em bash:

[[ $x == "$y" ]]
[[ $x = "$y" ]]
[ "$x" == "$y" ]
[ "$x" = "$y" ]

As duas primeiras variáveis $ x não precisam ser citadas. O Bash executa a divisão de palavras e a expansão do nome de caminho dentro [mas não dentro de [[:

$ x='a b'
$ [ -s $x ]
-bash: [: a: binary operator expected
$ [[ -s $x ]]
$ ls
$ [ a = * ]
-bash: [: a: unary operator expected
$ [[ a = * ]]
$ 

[[ $x = "$y" ]] é uma comparação de string, mas [[ $x = $y ]] é uma expressão de correspondência de padrões:

$ y='a*'; [[ aa = "$y" ]]; echo $?
1
$ y='a*'; [[ aa = $y ]]; echo $?
0

-eq destina-se apenas a ser usado com números inteiros:

$ [[ x.x -eq x.x ]]
-bash: [[: x.x: syntax error: invalid arithmetic operator (error token is ".x")
$ x=9; [[ "x" -eq 9 ]]; echo $?
0

Veja também BashFAQ / 031: Qual é a diferença entre o teste, [e [[? .

    
por 11.04.2013 / 08:31