Tentando descobrir como converter um argumento em um número inteiro para executar aritmética e, em seguida, imprimi-lo, diga addOne.sh
:
echo $1 + 1
>>sh addOne.sh 1
prints 1 + 1
Tentando descobrir como converter um argumento em um número inteiro para executar aritmética e, em seguida, imprimi-lo, diga addOne.sh
:
echo $1 + 1
>>sh addOne.sh 1
prints 1 + 1
Respostas:
No bash, não se "converte um argumento em um número inteiro para executar aritmética". No bash, as variáveis são tratadas como número inteiro ou string, dependendo do contexto.
Para executar aritmética, você deve chamar o operador de expansão aritmética $((...))
. Por exemplo:
$ a=2
$ echo "$a + 1"
2 + 1
$ echo "$(($a + 1))"
3
ou geralmente preferido:
$ echo "$((a + 1))"
3
Você deve estar ciente de que o bash (ao contrário de ksh93, zsh ou yash) executa apenas aritmética inteira . Se você possui números de ponto flutuante (números com decimais), existem outras ferramentas para ajudá-lo. Por exemplo, use bc
:
$ b=3.14
$ echo "$(($b + 1))"
bash: 3.14 + 1: syntax error: invalid arithmetic operator (error token is ".14 + 1")
$ echo "$b + 1" | bc -l
4.14
Ou você pode usar um shell com suporte aritmético de ponto flutuante em vez de bash:
zsh> echo $((3.14 + 1))
4.14
Em bash
, você pode executar a conversão de qualquer coisa para inteiro usando printf -v :
printf -v int '%d\n' "$1" 2>/dev/null
O número flutuante será convertido em número inteiro, enquanto qualquer coisa que não seja parecida com um número será convertida em 0. A exponenciação será truncada para o número anterior e
Exemplo:
$ printf -v int '%d\n' 123.123 2>/dev/null
$ printf '%d\n' "$int"
123
$ printf -v int '%d\n' abc 2>/dev/null
$ printf '%d\n' "$int"
0
$ printf -v int '%d\n' 1e10 2>/dev/null
$ printf '%d\n' "$int"
1
printf -v
isso, pode ser alcançado com a substituição de comandos:int="$(printf '%d' 123.123 2>/dev/null)"
bash
você usou?
Uma situação semelhante surgiu recentemente ao desenvolver scripts bash para execução nos ambientes Linux e OSX. O resultado de um comando no OSX retornou uma sequência contendo o código do resultado; ou seja, " 0"
. Obviamente, isso falhou ao testar corretamente no seguinte caso:
if [[ $targetCnt != 0 ]]; then...
A solução foi forçar (ou seja, 'converter') o resultado para um número inteiro, semelhante ao que @ John1024 respondeu acima, para que funcione conforme o esperado:
targetCnt=$(($targetCnt + 0))
if [[ $targetCnt != 0 ]]; then...
==
etc em [[
(também [
conhecido como test
) faça comparação de strings. Existem diferentes operadores para comparação aritmética, por exemplo [[ $targetcnt -ne 0 ]]
; consulte a página de manual (ou informações) em Expressões condicionais. Para aparar espaços especificamente, você pode usar [
a expansão de variáveis não citadas [ $targetcnt == 0 ]
para obter a divisão de palavras padrão (NÃO feita em [[
), mas em geral essa abordagem leva você ao perigo.
Se preocupam com códigos de cores, mesmo em trace ( -x
) eles não aparecerão, o que o denunciaria é que a string que deveria ser um número está entre aspas, não importa como você a imprima.
$((var+var))
falhas embora se você echo
ou os printf
dois vars são iguais. Não conheço a correção, pois só consegui corrigi-la desativando os códigos de cores na fonte da saída. Para identificá-lo nos logs de rastreamento, você verá a variável ofensiva atribuída como var='0'
deveria ser simplesmentevar=0
sed
se você não pode desativá-lo
printf "1 + %s\n" $1 won't do ?