AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 782661
Accepted
dr_
dr_
Asked: 2024-08-28 21:08:35 +0800 CST2024-08-28 21:08:35 +0800 CST 2024-08-28 21:08:35 +0800 CST

Qual é a diferença entre '$var' e 'var' em uma expansão aritmética?

  • 772

O Bash aceita ambas as sintaxes:

FOO=$(($BAR + 42))

e

FOO=$((BAR + 42))

Qual é o correto / mais portátil / menos propenso a erros? Ou ambos são igualmente válidos?

bash
  • 1 1 respostas
  • 352 Views

1 respostas

  • Voted
  1. Best Answer
    ilkkachu
    2024-08-28T21:29:11+08:002024-08-28T21:29:11+08:00

    Depende do que você quer fazer, mas você deve validar todas as entradas usadas no contexto aritmético primeiro (veja o final).


    Expansões de parâmetros como $varsubstituições de comandos são feitas antes que a expressão aritmética em si seja analisada. (*) Essa expansão acontece sem levar em conta a sintaxe aritmética, então $varvocê pode mexer nisso.

    Por outro lado, sem o $sinal, varé avaliado após a expressão aritmética ser analisada, e deve ser algo que avalie um valor. Pode ser uma expressão completa no Bash (**) .

    (* exceto que alguns shells fazem exceções para que algo como $(( a[$key] = 1 ))funcione mesmo que keyseja ].)

    (** A maioria dos outros shells também permite expressões completas em variáveis, mas não, por exemplo, Dash, no /bin/shDebian e Ubuntu.)


    Portanto, por exemplo, usar $varpode produzir um erro de sintaxe se a variável estiver vazia, enquanto com varserá tratado como zero.

    $ echo $((10 - var))
    10
    $ echo $((10 - $var))
    bash: 10 - : syntax error: operand expected (error token is "- ")
    

    10 - $varproduz apenas 10 -, uma expressão inválida. (Isso não acontece no seu exemplo de $BAR + 42porque + 42é uma expressão válida.)

    Por outro lado, você pode $varincluir expressões parciais:

    $ op=+; echo $(( 1 $op 2 ))
    3
    

    Com var, você só pode incluir subexpressões completas (em Bash):

    $ var=1+2
    $ echo $(( 10 *  var  ))
    30
    

    mas observe que usar $varaqui mudaria a ordem de avaliação!

    $ var=1+2
    $ echo $(( 10 * $var  ))
    12
    

    Aqui, a variável é primeiro expandida, resultando em 10 * 1+2, que é então analisado usando as regras aritméticas normais, multiplicando primeiro, sendo o mesmo que (10 * 1) + 2.

    $(( 10 * var ))sem o cifrão efetivamente coloca parênteses implícitos ao redor da variável, então é um pouco como $(( 10 * (1+2) )).

    Como parte da interpretação de variáveis ​​como expressões completas, o Bash seguirá a cadeia de nomes se uma variável nomear outra:

    $ one=two two=three three=four four=4; echo $(( one ))
    4
    

    A forma sem o cifrão só funciona para variáveis ​​nomeadas reais. Se você quiser usar os parâmetros posicionais $1, $2... ou variáveis ​​especiais como $#ou $?em aritmética, você terá que usar a forma cifrão. (O que deve ser bem óbvio, mas ainda assim.)

    Veja também Bash: expansão aritmética, expansão de parâmetros e o operador vírgula para outra diferença interessante.


    Embora você deva citar expansões como de costume , você não precisa citar expansões de variáveis ​​dentro da expressão aritmética, e fazer isso quebraria muitos shells. Então, use "$(( ...))", mas não $(( "$foo" ))(por exemplo, zsh croaks em i=123; echo $(( "$i" )))


    Independentemente de tudo isso , observe que a avaliação aritmética do Bash é vulnerável a injeções de comando triviais em ambos os casos, como:

    $ var='a[$(date >&2)]'
    $ echo $(( $var * 10 ))
    Wed Aug 28 16:25:57 EEST 2024
    0
    $ echo $((  var * 10 ))
    Wed Aug 28 16:26:49 EEST 2024
    0
    

    Isso significa que se você obtiver valores de fora, você deve validá-los primeiro, antes de usá-los em um contexto aritmético. E se depois dessa validação você souber que tem um número simples, não importa qual forma você use.

    (Isso não acontece no Dash, já que ele não suporta arrays, e o zsh parece não cair nessa.)

    • 10

relate perguntas

  • exportar variáveis ​​​​env programaticamente, via stdout do comando [duplicado]

  • Problema estranho ao passar variáveis ​​do arquivo de texto

  • Enquanto a linha lê mantendo os espaços de escape?

  • ordem de substituição de processos `te` e `bash`

  • Execute um script muito lento até que seja bem-sucedido

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Possível firmware ausente /lib/firmware/i915/* para o módulo i915

    • 3 respostas
  • Marko Smith

    Falha ao buscar o repositório de backports jessie

    • 4 respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    user12345 Falha ao buscar o repositório de backports jessie 2019-03-27 04:39:28 +0800 CST
  • Martin Hope
    Carl Por que a maioria dos exemplos do systemd contém WantedBy=multi-user.target? 2019-03-15 11:49:25 +0800 CST
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve