Alguém pode explicar a diferença entre -eq
e ==
no script bash?
Existe alguma diferença entre os seguintes?
[ $a -eq $b ]
e [ $a == $b ]
Simplesmente isso ==
é usado apenas quando as variáveis contêm números?
É o contrário: =
e ==
para comparações de strings, -eq
é para numéricas. -eq
está na mesma família como -lt
, -le
, -gt
, -ge
, e -ne
, se isso ajuda a lembrar qual é qual.
==
é um bash-ismo, a propósito. É melhor usar o POSIX =
. No bash, os dois são equivalentes e, na planície, sh =
é o único com garantia de funcionamento.
$ a=foo
$ [ "$a" = foo ]; echo "$?" # POSIX sh
0
$ [ "$a" == foo ]; echo "$?" # bash specific
0
$ [ "$a" -eq foo ]; echo "$?" # wrong
-bash: [: foo: integer expression expected
2
(Observação: cite as expansões variáveis! Não deixe as aspas duplas acima.)
Se você estiver escrevendo um #!/bin/bash
roteiro, então eu recomendo usar [[
vez . A forma dobrada tem mais recursos, sintaxe mais natural e menos truques que o farão mal. As aspas duplas não são mais necessárias $a
, por exemplo:
$ [[ $a == foo ]]; echo "$?" # bash specific
0
Veja também:
[[
como um todo, é um ksh-ismo da década de 1980 que o bash (e muitas outras conchas) adotou. Esse é o ponto inteiro - se você tem[[
em tudo , então você pode seguramente assumir que todas as extensões ksh implementado em torno dele (fnmatch()
estilo de correspondência de padrões, ERE expressões regulares com=~
, e sim, a supressão da cadeia de divisão e sistema de arquivos englobamento) será acessível. Como a[[
sintaxe não é POSIX na sua totalidade, não há perda de portabilidade adicional ao assumir que os recursos com os quais ele nasceu estarão disponíveis.[[ $var = $pattern ]]
, se você quer o que de outra forma seria interpretado como um padrão fnmatch em vez disso ser interpretada como uma string literal. A stringfoo
não tem interpretação não literal, deixando as aspas totalmente seguras; é apenas se o OP quiser corresponder, digamosfoo*
(com o asterisco como literal, não significando nada que possa vir após a sequênciafoo
), que aspas ou escape serão necessários.[[
sendo um basismo (indicando que esse era o único motivo pelo qual você não estava dando +1 na resposta).[ ... ]
e duplo sinal de igual==
. : - /Depende da construção de teste em torno do operador. Suas opções são parênteses duplos, chaves duplas, chaves simples ou teste
Se você usa ((...)) , está testando a equidade aritmética com
==
C:(Nota:
0
significatrue
no sentido Unix e diferente de zero é um teste que falhou)Usar
-eq
dentro de parênteses duplos é um erro de sintaxe.Se você estiver usando [...] (ou chaves simples) ou [...] [...] (ou chaves duplas), ou
test
poderá usar um de -eq, -ne, -lt, -le, -gt ou -ge como uma comparação aritmética .O
==
interior de chaves simples ou duplas (outest
comando) é um dos operadores de comparação de cadeias :Como operador de cadeia,
=
é equivalente==
e observe o espaço em branco ao redor=
ou==
é obrigatório.Enquanto você pode fazer
[[ 1 == 1 ]]
ou[[ $(( 1+1 )) == 2 ]]
está testando a igualdade de cadeias - não a igualdade aritmética.Portanto,
-eq
produz o resultado provavelmente esperado que o valor inteiro de1+1
seja igual a2
, embora o RH seja uma string e tenha um espaço à direita:Enquanto uma comparação de cadeias de caracteres pega o espaço à direita e, portanto, a comparação de cadeias falha:
E uma comparação incorreta de cadeias pode produzir a resposta errada completa. '10' é lexicograficamente menor que '2'; portanto, uma comparação de string retorna
true
ou0
. Muitos são mordidos por esse bug:vs o teste correto para 10 sendo aritmeticamente menor que 2:
Nos comentários, há uma questão da razão técnica, usando o número inteiro
-eq
em strings retorna True para strings que não são iguais:O motivo é que o Bash não é digitado . Isso
-eq
faz com que as seqüências sejam interpretadas como números inteiros, se possível, incluindo a conversão de base:E
0
se Bash achar que é apenas uma string:Então
[[ "yes" -eq "no" ]]
é equivalente a[[ 0 -eq 0 ]]
Última observação: muitas extensões específicas do Bash para as Construções de Teste não são POSIX e, portanto, falharão em outros shells. Outras conchas geralmente não suportam
[[...]]
e((...))
ou==
.fonte
[[ "yes" -eq "no" ]]
retornar True. Como o bash coage essas strings a valores inteiros que podem ser comparados? ;-)[[ "yes" -eq "no" ]]
são equivalentes a[[ "yes" -eq 0 ]]
ou[[ "yes" -eq "any_noninteger_string" ]]
- All True. A-eq
comparação de forças inteiras. O"yes"
é interpretado como um número inteiro0
; a comparação é True se o outro número inteiro for um0
ou o resultado da sequência0
.==
nos exemplos de código e apenas mencionando (portátil, padronizado)=
embaixo.==
é um alias específico do bash=
e executa uma comparação de sequência (lexical) em vez de uma comparação numérica.eq
sendo uma comparação numérica, é claro.Por fim, geralmente prefiro usar o formulário
if [ "$a" == "$b" ]
fonte
==
aqui é uma forma incorreta, pois somente=
é especificado pelo POSIX.==
-lo, coloque-o entre[[
e]]
. (E certifique-se de que a primeira linha do seu script especifique o uso/bin/bash
).Caras: Várias respostas mostram exemplos perigosos. O exemplo do OP
[ $a == $b ]
usou especificamente a substituição de variáveis não citadas (a partir de outubro de 17). Pois[...]
isso é seguro para a igualdade de cadeias.Mas se você enumerar alternativas como
[[...]]
, deve informar também que o lado direito deve ser citado. Se não citado, é uma correspondência de padrão! (Na página de manual do bash: "Qualquer parte do padrão pode ser citada para forçá-lo a corresponder como uma string.").Aqui no bash, as duas instruções que produzem "yes" correspondem a padrões, outras três são igualdade de cadeias:
fonte
[ "$lht" = "$rht" ]
com as aspas para ser confiável, mesmo para a igualdade. Se você tiver criado um arquivo comtouch 'Afoo -o AB'
,[ $lft = $rht ]
retornará true, mesmo que esse nome não seja idêntico aAB
.