Evite loops nas conchas.
Se você deseja fazer aritmética, use awkou bc:
awk '
BEGIN{
for (i = 4.00; i < 5.42; i+ = 0.02)
print i
}'
Ou
bc << EOF
for (i = 4.00; i < 5.42; i += 0.02) i
EOF
Observe que awk(ao contrário de bc) funciona com a doublerepresentação do número de ponto flutuante dos seus processadores (provavelmente do tipo IEEE 754 ). Como resultado, como esses números são aproximações binárias desses números decimais, você pode ter algumas surpresas:
$ gawk 'BEGIN{for (i=0; i<=0.3; i+=0.1) print i}'
0
0.1
0.2
Se você adicionar um, OFMT="%.17g"poderá ver o motivo da falta 0.3:
$ gawk 'BEGIN{OFMT="%.17g"; for (i=0; i<=0.5; i+=0.1) print i}'
0
0.10000000000000001
0.20000000000000001
0.30000000000000004
0.40000000000000002
0.5
bc faz precisão arbitrária e não tem esse tipo de problema.
Observe que, por padrão (a menos que você modifique o formato de saída com OFMTou use printfespecificações de formato explícitas), awkuse %.6gpara exibir números de ponto flutuante, portanto, alternaria para 1e6 e acima para números de ponto flutuante acima de 1.000.000 e truncaria a parte fracionária para números altos (100000.02 seria exibido como 100000).
Se você realmente precisa usar um loop shell, porque, por exemplo, você deseja executar comandos específicos para cada iteração desse loop, use um shell com flutuante apoio aritmética de ponto como zsh, yashou ksh93ou gerar a lista de valores com um comando como acima (ou, seqse disponível) e faça um loop sobre sua saída.
Gostar:
unset -v IFS # configure split+glob for default word splitting
for i in $(seq 4 0.02 5.42); do
something with "$i"
done
Ou:
seq 4 0.02 5.42 | while IFS= read i; do
something with "$i"
done
a menos que você ultrapasse os limites dos números de ponto flutuante do processador, seqlida com os erros incorridos pelas aproximações de ponto flutuante com mais graciosidade do que a awkversão acima.
Se você não possui seq(um comando GNU), pode torná-lo mais confiável como uma função como:
seq() { # args: first increment last
bc << EOF
for (i = $1; i <= $3; i += $2) i
EOF
}
Isso funcionaria melhor para coisas como seq 100000000001 0.000000001 100000000001.000000005. Observe, no entanto, que ter números com precisão arbitrariamente alta não ajudará muito se vamos passá-los para comandos que não os suportam.