Eu quero fazer um loop for no bash com 0,02 como incrementos eu tentei
for ((i=4.00;i<5.42;i+=0.02))
do
commands
done
mas não funcionou.
bash
for
floating-point
Mehrshad
fonte
fonte
bc
, mas parar no 4.52 pode ser complicado. usar @roaima sugestão, temos var auxiliar com o passo de 2, e a utilizaçãoi=$(echo $tmp_var / 100 | bc)
Respostas:
A leitura da
bash
página de manual fornece as seguintes informações:e então temos esta seção
Portanto, pode-se ver claramente que você não pode usar um
for
loop com valores não inteiros.Uma solução pode ser simplesmente multiplicar todos os seus componentes de loop por 100, permitindo que você os use posteriormente, desta forma:
fonte
k=400;k<542;k+=2
pois evita possíveis problemas aritméticos de ponto flutuante.bc
), bifurca um processo, cria um arquivo temporário (para a cadeia de caracteres here), executabc
nele (o que implica carregar bibliotecas executáveis e compartilhadas e inicializá-los), aguarde e limpe. Executarbc
uma vez para executar o loop seria muito mais eficiente.i=$(bc <<< "scale...")
oui=$(echo "scale..." | bc)
<<<
vem)bash
eksh
. Observe que alternar para outro shell quebash
lhe dará um aumento de desempenho melhor do que usar a outra sintaxe.<<<
(zsh, mksh, ksh93, yash) também suportam aritmética de vírgula flutuante (zsh
,ksh93
,yash
)).Evite loops nas conchas.
Se você deseja fazer aritmética, use
awk
oubc
:Ou
Observe que
awk
(ao contrário debc
) funciona com adouble
representaçã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:Se você adicionar um,
OFMT="%.17g"
poderá ver o motivo da falta0.3
: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
OFMT
ou useprintf
especificações de formato explícitas),awk
use%.6g
para 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
,yash
ouksh93
ou gerar a lista de valores com um comando como acima (ou,seq
se disponível) e faça um loop sobre sua saída.Gostar:
Ou:
a menos que você ultrapasse os limites dos números de ponto flutuante do processador,
seq
lida com os erros incorridos pelas aproximações de ponto flutuante com mais graciosidade do que aawk
versão acima.Se você não possui
seq
(um comando GNU), pode torná-lo mais confiável como uma função como: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.fonte
unset IFS
no primeiro exemplo?IFS=$'\n'
mas isso não funciona em todas as conchas. OuIFS='<a-litteral-newline-here>'
mas isso não é muito legível. Ou então, podemos dividir as palavras (espaço, tabulação, nova linha) como você obtém com o valor padrão de $ IFS ou se você desarmar o IFS e também trabalhar aqui.IFS
, porque sabemos queseq
a saída não possui espaços em que precisamos evitar a divisão. Está presente principalmente para garantir que você saiba que esse exemplo dependeIFS
, o que pode ser importante para um comando de geração de lista diferente.Use "seq" - imprima uma sequência de números
seq PRIMEIRO INCREMENTO ÚLTIMO
fonte
Como outros sugeriram, você pode usar o bc:
fonte