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