Comparando inteiros: expressão aritmética ou expressão condicional

No Bash, dois inteiros podem ser comparados usando expressão condicional

arg1 OP arg2

OP é um de -eq, -ne, -lt, -le, -gt, ou -ge. Esses operadores binários aritméticos retornam verdadeiro se arg1 for igual a, não igual a, menor que, menor ou igual a, maior que ou maior 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 inteiros? Quando usar qual?

Por exemplo, [[ 3 -lt 2 ]] usa expressão condicional e (( 3 < 2 )) usa expressão aritmética. Ambos retornam 0 quando a comparação é verdadeira

Ao comparar dois inteiros, esses dois métodos sempre podem ser usados alternadamente? Se sim, por que o Bash tem dois métodos em vez de um?

Comentários

  • = != < <= > >= comparar strings . 1 -eq 01, mas 1 != 01 e 8 -lt 42, mas 8 > 42
  • Eles estão sobrecarregados em expressões aritméticas.
  • você ‘ terá que pesquisar nos changelogs do bash para descobrir quando cada recurso foi adicionado. Suspeito que as expressões aritméticas foram adicionadas muito depois do comando de teste.
  • Não estou perguntando sobre a comparação de strings. @muru.

Resposta

Sim, temos duas maneiras diferentes de comparar dois números inteiros.

Parece que esses fatos não são amplamente aceitos neste fórum:

  1. Dentro do idioma [ ], os operadores para 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 idioma, =, <, etc. são operadores de string.

  2. Dentro do idioma (( )), os operadores para comparação aritmética são == , !=, <, <=, > e >=.

    Não, isso não é um “Aritmo expansão ética “(que começa com $) 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. Ele poderia ser usado assim:

if (( 2 > 1 )); then ... 

Por que temos duas maneiras diferentes de comparar dois números inteiros?

Acho que o último (( )) foi desenvolvido como uma maneira mais simples de realizar testes aritméticos. É quase o mesmo que $(( )), mas não tem saída.

Por que dois? Bem, o mesmo que porque temos dois printf (externos e internos) ou quatro testes (externos test, internos test, [ e [[). É assim que as cascas crescem, melhorando alguma área em um ano, melhorando outra 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 [ ] funciona e um (( )) funciona internamente, mas: qual é melhor comparar dois inteiros? Qualquer um !.

Ao comparar dois inteiros, esses dois métodos podem ser sempre usados de forma intercambiável?

Para dois números, sou obrigado a dizer sim.
Mas, para variáveis, expansões , operações matemáticas, pode haver diferenças importantes que devem favorecer um ou outro. Não posso dizer que absolutamente ambos são iguais. Por um lado, o (( )) poderia realizar várias operações matemáticas em sequência:

if (( a=1, b=2, c=a+b*b )); then echo "$c"; fi 

Se sim, por que o Bash tem dois métodos em vez de um?

Se ambos são úteis, por que não ?.

Comentários

  • = é uma atribuição e == é uma comparação em expansões aritméticas. A pergunta o cita corretamente. Mas a resposta está errada.
  • Além disso, ( não é uma palavra reservada em bash, portanto, não há necessidade de colocar espaços em torno de ((, como oposto a [ ou [[

Resposta

Historicamente, o comando test existia primeiro (pelo menos desde a Sétima edição do Unix em 1979). Ele usou os operadores = e != para comparar strings e -eq, -ne, -lt, etc. para comparar números. Por exemplo, test 0 = 00 é falso, mas test 0 -eq 00 é verdadeiro. Não sei por que essa sintaxe foi escolhida, mas pode ter sido para evitar o uso de < e >, que o shell teria analisados como operadores de redirecionamento. O comando test obteve outra sintaxe alguns anos depois: [ … ] é equivalente a test ….

A [[ … ]] sintaxe condicional, dentro da qual < e > podem ser usados como operadores sem aspas, foi adicionado posteriormente, em ksh. Manteve compatibilidade com versões anteriores de [ … ], então usou os mesmos operadores, mas adicionou < e > para comparar strings (por exemplo, [[ 9 > 10 ]] mas [[ 9 -lt 10 ]]). Para obter mais informações, consulte usando colchetes simples ou duplos – bash

Expressões aritméticas também vieram depois de 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 C “s:==para igualdade,<=para menos ou igual, etc.

Sétima Edição do Unix não tinha expressões aritméticas, mas tinha o expr comando , que também implementou um Sintaxe semelhante a C para operações inteiras, incluindo seus operadores de comparação. Em um script de shell, os caracteres < e > devem ser citados para protegê-los do shell, por exemplo, if expr 1 \< 2; … é equivalente a if test 1 -lt 2; …. A adição de expressões aritméticas ao shell tornou a maioria dos usos de expr obsoleto, portanto não é “muito conhecido hoje.

Em um script sh, você” d geralmente usa expressões aritméticas para calcular um valor inteiro e [ … ] para comparar inteiros.

if [ "$((x + y))" -lt "$z" ]; then … 

Em um ksh , script bash ou zsh, você pode usar ((…)) para ambos.

if ((x + y < z)); then … 

O [[ … ]] o formulário é útil se você deseja usar condicionais envolvendo coisas que não sejam inteiros.

Resposta

De acordo com a página do manual de teste, = e! = são usados para comparações de strings, enquanto as expressões -eq, -gt, -lt, -ge, -le e -ne são comparações de inteiros. Sempre segui essa convenção ao escrever scripts de shell e ela sempre funciona. Esteja ciente de que, se houver 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 string / número sem pensar muito. Um computador, por outro lado, não sabe se 987 é um número ou uma string de caracteres. Você precisa que os diferentes operadores digam ao computador o que fazer para obter o resultado correto. Há algumas informações adicionais aqui que explicam um pouco da história. Essencialmente, as variáveis não foram digitadas e permaneceram assim para compatibilidade histórica.

Comentários

  • Em minha postagem, = e != são operadores aritméticos, enquanto a página de manual de test mostra apenas operadores de expressão condicional.

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *