No Bash, dois números inteiros podem ser comparados usando expressão condicional
arg1 OP arg2
OP é um dos
-eq
,-ne
,-lt
,-le
,-gt
, ou-ge
. Esses operadores binários aritméticos retornam true se arg1 for igual a, diferente de, menor que, menor que ou igual a, maior que ou maior que ou igual a arg2 , respectivamente. Arg1 e arg2 podem ser inteiros positivos ou negativos.
ou expressão aritmética:
<= >= < >
comparação
== !=
igualdade e desigualdade
Por que temos duas maneiras diferentes de comparar dois números inteiros? Quando usar qual?
Por exemplo, [[ 3 -lt 2 ]]
usa expressão condicional e (( 3 < 2 ))
expressão aritmética. Ambos retornam 0 quando a comparação é verdadeira
Ao comparar dois números inteiros, esses dois métodos sempre podem ser usados de forma intercambiável? Se sim, por que o Bash tem dois métodos em vez de um?
= != < <= > >=
comparar cadeias .1 -eq 01
mas1 != 01
e8 -lt 42
mas8 > 42
Respostas:
Sim, temos duas maneiras diferentes de comparar dois números inteiros.
Parece que esses fatos não são amplamente aceitos neste fórum:
Dentro da linguagem
[ ]
dos operadores de comparação aritmética são-eq
,-ne
,-lt
,-le
,-gt
e-ge
.Como eles também estão dentro de um comando de teste e dentro de um
[[ ]]
.Sim dentro deste expressões idiomáticas,
=
,<
, etc, são operadores de string.Dentro da linguagem
(( ))
dos operadores de comparação aritmética são==
,!=
,<
,<=
,>
, e>=
.Não, essa não é uma "expansão aritmética" (que começa com a
$
) como$(( ))
. É definido como um "Comando composto" no man bash.Sim, segue as mesmas regras (internamente) da "expansão aritmética", mas não tem saída, apenas um valor de saída. Pode ser usado assim:
Por que temos duas maneiras diferentes de comparar dois números inteiros?
Eu acho que o último
(( ))
foi desenvolvido como uma maneira mais simples de realizar testes aritméticos. É quase o mesmo que o,$(( ))
mas simplesmente não tem saída.Por que dois? Bem, a mesma que por isso que temos dois
printf
(externa e builtin) ou quatro teste (externotest
, builtintest
,[
e[[
). É assim que as conchas crescem, melhorando alguma área em um ano, melhorando outras no próximo ano.Quando usar qual?
Essa é uma pergunta muito difícil, porque não deve haver diferença efetiva. Claro que existem algumas diferenças na maneira como um
[ ]
trabalho e um(( ))
trabalho internamente, mas: qual é o melhor para comparar dois números inteiros? Qualquer um!.Ao comparar dois números inteiros, esses dois métodos sempre podem ser usados de forma intercambiável?
Por dois números, sou obrigado a dizer que sim.
Mas para variáveis, expansões, operações matemáticas, pode haver diferenças importantes que devem favorecer uma ou outra. Não posso dizer que absolutamente ambos sejam iguais. Por um lado, o
(( ))
poderia executar várias operações matemáticas em sequência:Se sim, por que o Bash tem dois métodos em vez de um?
Se ambos são úteis, por que não?
fonte
=
é uma tarefa e==
é uma comparação em expansões aritméticas. A pergunta cita corretamente. Mas a resposta está errada.Historicamente, o
test
comando existia primeiro (pelo menos desde a Unix Seventh Edition em 1979). Usou-se os operadores=
e!=
para comparar cadeias, e-eq
,-ne
,-lt
, etc, para comparar os números. Por exemplo,test 0 = 00
é falso, mastest 0 -eq 00
é verdadeiro. Não sei por que essa sintaxe foi escolhida, mas pode ter sido para evitar o uso<
e>
, que o shell teria analisado como operadores de redirecionamento. Otest
comando obteve outra sintaxe alguns anos depois:[ … ]
é equivalente atest …
.A
[[ … ]]
sintaxe condicional, dentro da qual<
e>
pode ser usada como operadores sem citar, foi adicionada posteriormente, no ksh. Ele manteve a compatibilidade com versões anteriores e[ … ]
, portanto, usou os mesmos operadores, mas adicionou<
e>
comparou seqüências de caracteres (por exemplo,[[ 9 > 10 ]]
mas[[ 9 -lt 10 ]]
). Para obter mais informações, consulte Uso de colchetes simples ou duplos - bashAs expressões aritméticas também vieram depois do
test
comando, no shell Korn , em algum momento da década de 1980. Eles seguiram a sintaxe da linguagem C, que era muito popular nos círculos Unix. Assim, eles usaram operadores de C:==
para igualdade,<=
para menor ou igual, etc.O Unix Seventh Edition não tinha expressões aritméticas, mas possuía o
expr
comando , que também implementava uma sintaxe do tipo C para operações inteiras, incluindo seus operadores de comparação. Em um script de shell, os caracteres<
e>
tiveram que ser citados para protegê-los do shell, por exemplo,if expr 1 \< 2; …
é equivalente aif test 1 -lt 2; …
. A adição de expressões aritméticas ao shell fez com que a maioria dos usosexpr
fosse obsoleta, por isso não é bem conhecido hoje.Em um script sh, você geralmente usaria expressões aritméticas para calcular um valor inteiro e
[ … ]
comparar números inteiros.Em um script ksh, bash ou zsh, você pode usar
((…))
para ambos.O
[[ … ]]
formulário é útil se você deseja usar condicionais envolvendo outras coisas além de números inteiros.fonte
De acordo com a página do manual de teste, = e! = São usados para comparações de cadeias, enquanto as expressões -eq, -gt, -lt, -ge, -le e -ne são comparações inteiras. Eu sempre segui essa convenção ao escrever scripts de shell e sempre funciona. Esteja ciente de que se você tiver variáveis na expressão, pode ser necessário citar as variáveis de alguma forma para evitar uma comparação nula.
No papel, fazemos comparações de string / número sem muita reflexão. Um computador, por outro lado, não sabe se 987 é um número ou uma sequência de caracteres. Você precisa dos diferentes operadores para informar ao computador o que fazer para obter o resultado certo. Há algumas informações adicionais aqui que explicam parte da história. Essencialmente, as variáveis não são tipadas e permaneceram assim para compatibilidade histórica.
fonte
=
e!=
são operadores aritméticos, enquanto a página de manualtest
mostra apenas operadores de expressão condicional.