Qual é a diferença entre sinais de igual simples e duplos (=) em comparações de shell?

Qual é a diferença entre sinais de igual simples e duplos (=) em comparações de shell?

Leia que para comparar strings internas ifprecisamos 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?

Responder1

In bash(como de kshonde bashcopiou essa sintaxe), [[ $a == $b ]]não é comparação, é correspondência de padrões. Você precisa [[ $a == "$b" ]]de uma comparação de igualdade byte a byte. =é o mesmo que ==em qualquer shell que suporte [[...]].

[[...]]não é shsintaxe padrão. O[ comandoé padrão, e o padrãocomparaçãooperador existe =(embora algumas [implementações também reconheçam ==¹).

Assim como em qualquer argumento para qualquer comando, as expansões de variáveis ​​devem ser colocadas entre aspas para evitardividir+globoe remoção vazia (somente esta última sendo realizada em zsh), então:

[ "$a" = "$b" ]

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

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

Para completar, outrosigual à igualdadeoperadores que você pode encontrar em scripts de shell:

  • [ "$a" -eq "$b" ]: [operador padrão para comparar números inteiros decimais. Algumas [implementações permitem espaços em branco ao redor dos números, outras 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 ]qual seria o equivalente padrão (exceto que POSIXly, o comportamento só é especificado se $ae $bcontiver constantes inteiras) de:

  • ((a == b)), de ksh e também encontrado em zshe bash, retorna verdadeiro se a avaliação da expressão aritmética armazenada em $aproduzir o mesmo número que a de $b. Normalmente, isso é usado para comparar números. Observe que existem variações entre os shells sobre como as 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 octais).

  • expr "$a" = "$b"faz uma comparação de números se ambos os operandos forem reconhecidos como números inteiros decimais (alguns permitindo espaços em branco ao redor do número) e, caso contrário, verifica se os dois operandos de string têm a mesma ordem de classificação. Também falharia para valores de $aou $bque sejam exproperadores como (, substr...

  • awk -- 'BEGIN{exit !(ARGV[1] == ARGV[2])}' "$a" "$b": se $ae $bforem reconhecidos como números (pelo menos números inteiros decimais e de ponto flutuante como 1,2, -1,5e-4, espaços em branco iniciais ignorados, alguns também reconhecendo hexadecimal, 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 string byte a byte ou, como expruma strcoll()comparação, ou seja, se $ae $bclassifica da mesma forma.

Veja também:


¹ que inclui GNU [e o [embutido de ksh, bash, yash, alguns, embora não todos ash, shells baseados e zsh, no entanto, observe que em zsh,=cmdé um operador especial de expansão de nome de arquivo(expandido nos mesmos contextos que ~userestá) que se expande para o caminho do comando correspondente, então, a menos que você desative a equalsopção para desabilitar esse recurso, você precisará escrevê-lo [ "$a" '==' "$b" ]ou receberá um erro informando que o =comando Não foi encontrado. O mesmo para[ "$string" '=~' "$regexp" ]

Responder2

Estes são equivalentes no bash:

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

As duas primeiras variáveis ​​$x não precisam ser citadas. Bash realiza divisão de palavras e expansão de nome de caminho dentro de [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 strings, 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 deve ser usado apenas 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émBashFAQ/031: Qual é a diferença entre teste, [ e [[ ?.

Responder3

Ambos =e ==são operadores. Em algumas linguagens (como C) uma é usada para atribuir um valor a uma variável e a outra para comparar valores (resultado de expressões aritméticas). Na verdade, ambos os operadores são exatamente isso dentro da Avaliação Aritmética. A $((a=23))é uma tarefa, a $((a==23))é uma comparação aritmética.

$ echo "$((a=11)) $((a==23))" "$((a=23))" "$((a==23))"
11 0 23 1

Mas dentro das construções de teste (todastestee[…]e[[…]]) ambos os operadores têm o mesmo significado e executam a mesma operação.

Então, todas essas opções:

test "$a" =  "$b"
   [ "$a" =  "$b" ]
  [[ "$a" =  "$b" ]]
test "$a" == "$b"
   [ "$a" == "$b" ]
  [[ "$a" == "$b" ]]

Sãoequivalente dentrofestapara testar a igualdade binária (variáveis ​​citadas). Se a variável certa não estiver entre aspas, ela poderá ser interpretada como um padrão e correspondida de acordo: como um padrão, não como uma string literal.

Os operadores citados \=e \==também são equivalentes quando usados ​​em test e […]. Mas o operador citado \==falha por dentro [[…]].

Para outros shells os resultados são variados (o resultado correto deve ser Y -(true false), um código de saída diferente de 0 (true) e 1 (false) é relatado como falha wih ¤). Alguns shells falham - -(o código de saída é sempre 1).

                     | dash  ksh   bash  zsh   
  test a  =  "$b"    | Y -   Y -   Y -   Y -    
     [ a  =  "$b" ]  | Y -   Y -   Y -   Y -    
    [[ a  =  "$b" ]] | ¤ ¤   Y -   Y -   Y -    
  test a  == "$b"    | ¤ ¤   Y -   Y -   - -    
     [ a  == "$b" ]  | ¤ ¤   Y -   Y -   - -    
    [[ a  == "$b" ]] | ¤ ¤   Y -   Y -   Y -    
  test a \=  "$b"    | Y -   Y -   Y -   Y -    
     [ a \=  "$b" ]  | Y -   Y -   Y -   Y -    
    [[ a \=  "$b" ]] | ¤ ¤   Y -   - -   - -    
  test a \== "$b"    | ¤ ¤   Y -   Y -   Y -    
     [ a \== "$b" ]  | ¤ ¤   Y -   Y -   Y -    
    [[ a \== "$b" ]] | ¤ ¤   Y -   - -   - -

Todas as opções funcionam em ksh, os operadores entre aspas falham em bash e zsh (dentro [[…]]) e os sem aspas \=e \==também falham em zsh (fora de [[…]]).

informação relacionada