Alguém pode explicar a diferença entre -eqe ==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?
Alguém pode explicar a diferença entre -eqe ==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?
Respostas:
É o contrário: =e ==para comparações de strings, -eqé para numéricas. -eqestá 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/bashroteiro, 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:
[[ $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 string foonão tem interpretação não literal, deixando as aspas totalmente seguras; é apenas se o OP quiser corresponder, digamos foo*(com o asterisco como literal, não significando nada que possa vir após a sequência foo), 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:
$ (( 1==1 )); echo $?
0
$ (( 1==2 )); echo $?
1
(Nota: 0significa trueno sentido Unix e diferente de zero é um teste que falhou)
Usar -eqdentro de parênteses duplos é um erro de sintaxe.
Se você estiver usando [...] (ou chaves simples) ou [...] [...] (ou chaves duplas), ou testpoderá usar um de -eq, -ne, -lt, -le, -gt ou -ge como uma comparação aritmética .
$ [ 1 -eq 1 ]; echo $?
0
$ [ 1 -eq 2 ]; echo $?
1
$ test 1 -eq 1; echo $?
0
O ==interior de chaves simples ou duplas (ou testcomando) é um dos operadores de comparação de cadeias :
$ [[ "abc" == "abc" ]]; echo $?
0
$ [[ "abc" == "ABC" ]]; echo $?
1
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, -eqproduz o resultado provavelmente esperado que o valor inteiro de 1+1seja igual a 2, embora o RH seja uma string e tenha um espaço à direita:
$ [[ $(( 1+1 )) -eq "2 " ]]; echo $?
0
Enquanto uma comparação de cadeias de caracteres pega o espaço à direita e, portanto, a comparação de cadeias falha:
$ [[ $(( 1+1 )) == "2 " ]]; echo $?
1
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 trueou 0. Muitos são mordidos por esse bug:
$ [[ 10 < 2 ]]; echo $?
0
vs o teste correto para 10 sendo aritmeticamente menor que 2:
$ [[ 10 -lt 2 ]]; echo $?
1
Nos comentários, há uma questão da razão técnica, usando o número inteiro -eqem strings retorna True para strings que não são iguais:
$ [[ "yes" -eq "no" ]]; echo $?
0
O motivo é que o Bash não é digitado . Isso -eqfaz com que as seqüências sejam interpretadas como números inteiros, se possível, incluindo a conversão de base:
$ [[ "0x10" -eq 16 ]]; echo $?
0
$ [[ "010" -eq 8 ]]; echo $?
0
$ [[ "100" -eq 100 ]]; echo $?
0
E 0se Bash achar que é apenas uma string:
$ [[ "yes" -eq 0 ]]; echo $?
0
$ [[ "yes" -eq 1 ]]; echo $?
1
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== .
[[ "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 -eqcomparação de forças inteiras. O "yes"é interpretado como um número inteiro 0; a comparação é True se o outro número inteiro for um 0ou o resultado da sequência 0.
==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. eqsendo uma comparação numérica, é claro.
Por fim, geralmente prefiro usar o formulário if [ "$a" == "$b" ]
==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:
$ rht="A*"
$ lft="AB"
$ [ $lft = $rht ] && echo yes
$ [ $lft == $rht ] && echo yes
$ [[ $lft = $rht ]] && echo yes
yes
$ [[ $lft == $rht ]] && echo yes
yes
$ [[ $lft == "$rht" ]] && echo yes
$
[ "$lht" = "$rht" ] com as aspas para ser confiável, mesmo para a igualdade. Se você tiver criado um arquivo com touch 'Afoo -o AB', [ $lft = $rht ]retornará true, mesmo que esse nome não seja idêntico a AB.
[[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.