Divisão inteira flutuante e valor da variável de configuração

3

Atualmente, estou aprendendo o mundo dos scripts de bash. Estou ciente de que bash por si só não faz aritmética com inteiros flutuantes. Eu fiz algumas pesquisas e descobri que existem ferramentas que podem ajudar a fazer o trabalho. Eu decidi usar a ferramenta de calculadora bc . O único problema é a sintaxe. Eu sou capaz de obter resultados, mas não da maneira desejada. Como posso atribuir $N_RESULTS o valor da operação matemática?

//I get arithmetic error with this syntax
DECI=128.17333
let "N_RESULTS = ($DECI - 1) / 10 + 1" | bc -l
echo $N_RESULTS

_

//I get correct results if do something like this
DECI=128.17333
echo "($DECI - 1) / 10 + 1" | bc -l
    
por Code_Ed_Student 05.10.2014 / 05:05

1 resposta

2
N_RESULTS=$( echo "($DECI - 1) / 10 + 1" | bc -l )

O que let faz

Considere:

let "N_RESULTS = ($DECI - 1) / 10 + 1" | bc -l

Este pipeline tem duas partes. O primeiro é o comando let do shell. Por causa do símbolo | , a saída do comando let é passada para stdin do comando bc . Enquanto ' let é capaz de executar a aritmética inteira e pode atribuir valores à variável, ela não produz nenhuma saída. Portanto, mesmo que fosse executado corretamente, não passaria nada para bc .

Aqui está um exemplo de um comando let em funcionamento:

$ let "result = (123 - 1) / 10 + 1"
$ echo $result
13

Se, no entanto, fornecermos um argumento de ponto flutuante, um erro resultará:

$ let "result = (123.0 - 1) / 10 + 1"
bash: let: result = (123.0 - 1) / 10 + 1: syntax error: invalid arithmetic operator (error token is ".0 - 1) / 10 + 1")

O comando let , como o resto do shell, só faz aritmética inteira.

O que bc faz

bc faz aritmética de ponto flutuante e pode ser usado para atribuir e manipular variáveis:

$ echo "result = (123.0123 - 1) / 10 + 1; print result" | bc -l
13.20123000000000000000

Note, no entanto, que o acima não cria, por si só, quaisquer variáveis utilizáveis em shell. A definição de result expira quando o bc termina o processamento. Para passar o valor de volta ao shell, precisamos fazer uma atribuição de variável do shell, como:

$ result=$(echo "(123.0123 - 1) / 10 + 1" | bc -l )
$ echo $result
13.20123000000000000000

A construção $(...) é chamada de substituição de comando. Ele executa um comando, neste caso o pipeline echo e bc, e coloca seu stdout na linha de comando, onde é atribuído à variável result .

Como uma nota secundária, geralmente são consideradas práticas recomendadas usar nomes de letras minúsculas para suas variáveis de shell. As variáveis do shell do sistema são todas em maiúsculas e você não quer sobrescrever acidentalmente uma delas.

Qual é o bc equivalente para [[ $offset -lt $result ]]

Os comandos test do shell, incluindo [ e [[ , produzem um código de saída útil que pode ser usado em if , while e outros contextos, como && e || , onde os códigos de saída são usados para determinar o fluxo do programa. bc não emula esse comportamento. Ele retorna um código de saída de 0 para qualquer cálculo bem-sucedido. Ele retorna códigos de saída diferentes de zero se ocorrer um erro. Os exemplos abaixo mostram como, com a ajuda de grep , bc pode ser usado para definir códigos de saída úteis.

No GNU bc , expressões relacionais avaliam para 1 para true e 0 para false. Portanto, para testar se offset é menor que result , apenas verificamos se bc retorna 0 ou 1 . Aqui, grep é usado para examinar a saída de bc e definir um código de retorno apropriado que pode ser usado em if , while ou outros locais onde o shell testaria um código de retorno. Por exemplo:

$ offset=1.25; result=1.33
$ echo "$offset < $result" | bc -l | grep -q 1 && echo yes || echo no
yes
$ offset=1.35
$ echo "$offset < $result" | bc -l | grep -q 1 && echo yes || echo no
no

Em não-GNU bc , a mesma coisa pode ser feita, mas uma declaração if formal é necessária:

echo "if ($offset < $result) print 1 else print 0 " | bc -l | grep -q 1 && echo yes || echo no
    
por 05.10.2014 / 05:53

Tags