%20em%20compara%C3%A7%C3%B5es%20de%20shell%3F.png)
Leia que para comparar strings internas 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?
Responder1
In bash
(como de ksh
onde bash
copiou 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 é sh
sintaxe 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$a
e$b
contiver constantes inteiras) de:((a == b))
, de ksh e também encontrado emzsh
ebash
, retorna verdadeiro se a avaliação da expressão aritmética armazenada em$a
produzir 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$a
ou$b
que sejamexpr
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 iniciais ignorados, alguns também reconhecendo hexadecimal, octal ou qualquer coisa reconhecida porstrtod()
), então uma comparação numérica é executada. Caso contrário, dependendo da implementação, é uma comparação de string byte a byte ou, comoexpr
umastrcoll()
comparação, ou seja, se$a
e$b
classifica 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 ~user
está) que se expande para o caminho do comando correspondente, então, a menos que você desative a equals
opçã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 [[…]]
).