Tento formatar sua pergunta, mas ela ainda não está clara. printf "1 + %s\n" $1 won't do ?
Archemar 27/09/2015
Respostas:
89
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:
Usar $ (()) ou (()) não é seguro se você não souber quais são as strings (como a entrada do usuário). Considere o seguinte: foo = foo ((foo + = 0)) Isso travará o script ao tentar avaliar recursivamente foo. O mesmo acontece com: foo = foo foo = $ ((foo + 0))
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.1232>/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'1e102>/dev/null
$ printf '%d\n'"$int"1
Em outros shells sem printf -visso, pode ser alcançado com a substituição de comandos:int="$(printf '%d' 123.123 2>/dev/null)"
Adrian Günter
2
Isso não funciona no bash.
Michael Martinez
@MichaelMartinez tem certeza? Qual a versão que bashvocê usou?
cuonglm 23/01
GNU bash, versão 4.2.46 (1) -release (x86_64-redhat-linux-gnu)
Michael Martinez
5
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:
==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.
Dave_thompson_085
-2
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.
Votado, pois acho a sua resposta um pouco clara. Talvez você possa adicionar a que o script deve ser corrigido?
Time4Tea
essa foi a principal resposta na busca por bash + inteiro + string, então eu adicionei uma informação relacionada a ela que não foi incluída nas respostas, ou seja, quando as strings estão envolvidas em códigos de cores, pode não estar claro por que operações como $((var+var))falhas embora se você echoou os printfdois 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
desatou
O que você pode fazer é se certificar a saída não tem códigos de cores com sedse você não pode desativá-lo
printf "1 + %s\n" $1 won't do ?
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:ou geralmente preferido:
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
:Ou você pode usar um shell com suporte aritmético de ponto flutuante em vez de bash:
fonte
Por outro lado, você pode usar
expr
Ex:
fonte
Em
bash
, você pode executar a conversão de qualquer coisa para inteiro usando printf -v :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:
fonte
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: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:
fonte
==
etc em[[
(também[
conhecido comotest
) 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.fonte
$((var+var))
falhas embora se vocêecho
ou osprintf
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 comovar='0'
deveria ser simplesmentevar=0
sed
se você não pode desativá-lo