Unikaj pętli w muszlach.
Jeśli chcesz wykonywać arytmetykę, użyj awklub bc:
awk '
BEGIN{
for (i = 4.00; i < 5.42; i+ = 0.02)
print i
}'
Lub
bc << EOF
for (i = 4.00; i < 5.42; i += 0.02) i
EOF
Zauważ, że awk(w przeciwieństwie do bc) współpracuje z procesorami doublereprezentacji liczb zmiennoprzecinkowych (prawdopodobnie typu IEEE 754 ). W rezultacie, ponieważ te liczby są binarnymi przybliżeniami tych liczb dziesiętnych, możesz mieć pewne niespodzianki:
$ gawk 'BEGIN{for (i=0; i<=0.3; i+=0.1) print i}'
0
0.1
0.2
Jeśli dodasz OFMT="%.17g", możesz zobaczyć przyczynę braku 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 wykonuje dowolną precyzję, więc nie ma tego rodzaju problemów.
Zauważ, że domyślnie (chyba że zmienisz format wyjściowy za pomocą OFMTlub użyjesz printfjawnych specyfikacji formatu), awkużywa %.6gdo wyświetlania liczb zmiennoprzecinkowych, więc przełącza się na 1e6 i więcej dla liczb zmiennoprzecinkowych powyżej 1 000 000 i obcina część ułamkową dla wysokich liczb (100000,02 będzie wyświetlany jako 100000).
Jeśli naprawdę potrzebujesz użyć pętli powłoki, ponieważ na przykład chcesz uruchomić określone polecenia dla każdej iteracji tej pętli, użyj powłoki z obsługą arytmetyki zmiennoprzecinkowej zsh, yashlub, ksh93lub wygeneruj listę wartości za pomocą jednego polecenia, jak powyżej (lub seqjeśli jest dostępny) i zapętlić jego wynik.
Lubić:
unset -v IFS # configure split+glob for default word splitting
for i in $(seq 4 0.02 5.42); do
something with "$i"
done
Lub:
seq 4 0.02 5.42 | while IFS= read i; do
something with "$i"
done
o ile nie przekroczysz limitów liczb zmiennoprzecinkowych procesora, obsługa seqbłędów wynikających z przybliżeń zmiennoprzecinkowych jest bardziej płynna niż w przypadku awkwersji powyżej.
Jeśli nie masz seq(polecenia GNU), możesz uczynić je bardziej niezawodnym jako funkcja:
seq() { # args: first increment last
bc << EOF
for (i = $1; i <= $3; i += $2) i
EOF
}
To działałoby lepiej w przypadku takich rzeczy seq 100000000001 0.000000001 100000000001.000000005. Zauważ jednak, że posiadanie liczb z dowolnie wysoką precyzją niewiele pomoże, jeśli przekażemy je poleceniom, które ich nie obsługują.