Diferença entre let, expr e $ []

17

Eu quero saber exatamente qual é a diferença entre

a=$[1+1]
a=$((1+1))
let a=1+1
a=$(expr 1 + 1 )

Todos os 4 atribuem a variável a com 2, mas qual é a diferença?

Pelo que eu descobri até agora, é que expr é mais lento porque não é um shell embutido. Mas nada além disso.

    
por ADDB 24.07.2017 / 17:35

4 respostas

18

Todos eles lidam com aritmética, mas de maneiras diferentes e a variável é criada por meios diferentes. Algumas delas são específicas para bash shells, enquanto outras não são.

  • ((...)) é chamado de expansão aritmética, que é típica das conchas bash e ksh . Isso permite fazer uma simples aritmética integer , mas sem ponto flutuante. ((...)) é apenas uma ação, então $((..)) substitui a saída da operação.
  • $[...] é a antiga sintaxe para expansão aritmética que é obsoleta. Veja também . Isso provavelmente foi mantido para que os antigos scripts bash não quebrem. Isso não funcionou em ksh93 , então meu palpite é que essa sintaxe é bash-specific. NOTA : espaços são muito importantes aqui; não confunda $[1+1] com coisas como [ $a -eq $b ] . O [ com espaços é conhecido como o comando test e, normalmente, você o vê nas partes de tomada de decisão. É muito diferente em comportamento e propósito.
  • let é uma palavra-chave bash e ksh que permite a criação de variáveis com avaliação aritmética simples. Se você tentar atribuir uma string como let a="hello world" , receberá um erro de sintaxe. Funciona em bash e ksh93 .
  • $(...) é a substituição de comando, onde você literalmente pega a saída de um comando e atribui a uma variável. Seu comando aqui é expr , que recebe argumentos posicionais, como expr arg1 arg2 arg3 , de modo que os espaços são importantes. É como uma pequena calculadora de linha de comando para aritmética inteira, além de alguns tipos de coisas verdadeiro / falso e regex. Este é um comando de shell neutro.

Também é importante notar que a expansão aritmética e a substituição de comandos são especificadas pelo padrão POSIX , enquanto let e $[...] não são.

    
por Sergiy Kolodyazhnyy 24.07.2017 / 18:21
10
  • O comando

    let executa a avaliação aritmética e é um shell integrado.

    • Execute este comando e você não recebe nada (apenas avalia):

      let 1+2
      
  • $(( )) é usado para realizar expansão aritmética : leia aqui

    • Execute este e você receberá um erro (por causa da expansão):

      $((1+2))
      
  • $[ ] é a antiga sintaxe para expansão aritmética:

      

    O formato antigo $ [expression] está obsoleto e será removido no próximo lançamento do bash.    Página do Bash Man

  • expr é um comando binário, se você quiser fazer uma expansão aritmética dentro de um comando, você pode usá-lo:

    echo $(expr 1 + 2) 
    echo 'expr 1 + 2'
    
por Ravexina 24.07.2017 / 18:27
3

Como algumas das respostas acima mencionam especificamente ksh93 , vale a pena observar que ele pode fazer matemática de ponto flutuante, por exemplo:

$ print $((1.0/3)) 
0.333333333333333333

Você pode controlar a precisão da saída com printf, por exemplo:

$ printf "%.4f\n" $((1.0/3))
0.3333

Pelo menos um argumento deve ser especificado como um número de ponto flutuante como acima. Se ambos forem especificados como números inteiros, somente a matemática inteira é feita, por exemplo:

$ print $((1/3))  
0

Isso pode ser útil quando você precisar de matemática de ponto flutuante em um script de shell, já que você pode evitar chamar um comando externo.

    
por sneezy 29.09.2017 / 00:45
0

let não funciona no cron. Acho que isso é devido a let ter seu próprio ambiente. Use $((...)) desde que é POSIX. Por exemplo,

let x=1+2
echo x=$x

no cron, resulta em "x=", mas "x = 3" quando executado a partir do shell.

x=$((1+2))
echo x=$x

resulta em "x = 3" em todos os casos.

    
por SparkEV 11.01.2018 / 20:06

Tags