Próbując dowiedzieć się, jak przekonwertować argument na liczbę całkowitą w celu wykonania arytmetyki, a następnie wydrukować go, powiedz dla addOne.sh
:
echo $1 + 1
>>sh addOne.sh 1
prints 1 + 1
Próbując dowiedzieć się, jak przekonwertować argument na liczbę całkowitą w celu wykonania arytmetyki, a następnie wydrukować go, powiedz dla addOne.sh
:
echo $1 + 1
>>sh addOne.sh 1
prints 1 + 1
Odpowiedzi:
W bash nie wykonuje się „konwersji argumentu na liczbę całkowitą w celu wykonania arytmetyki”. W bash zmienne są traktowane jako liczba całkowita lub ciąg znaków w zależności od kontekstu.
Aby wykonać arytmetykę, należy wywołać arytmetyczny operator rozszerzenia $((...))
. Na przykład:
$ a=2
$ echo "$a + 1"
2 + 1
$ echo "$(($a + 1))"
3
lub ogólnie preferowane:
$ echo "$((a + 1))"
3
Należy pamiętać, że bash (w przeciwieństwie do ksh93, zsh lub yash) wykonuje tylko arytmetykę liczb całkowitych . Jeśli masz liczby zmiennoprzecinkowe (liczby dziesiętne), możesz skorzystać z innych narzędzi. Na przykład użyj bc
:
$ b=3.14
$ echo "$(($b + 1))"
bash: 3.14 + 1: syntax error: invalid arithmetic operator (error token is ".14 + 1")
$ echo "$b + 1" | bc -l
4.14
Lub możesz użyć powłoki z obsługą arytmetyki zmiennoprzecinkowej zamiast bash:
zsh> echo $((3.14 + 1))
4.14
W bash
można wykonać konwersję z dowolnej wartości na liczbę całkowitą za pomocą printf -v :
printf -v int '%d\n' "$1" 2>/dev/null
Liczba zmiennoprzecinkowa zostanie przekonwertowana na liczbę całkowitą, a nic nie będzie wyglądać tak, jakby liczba została przekonwertowana na 0. Potęgowanie zostanie obcięte do liczby przed e
Przykład:
$ printf -v int '%d\n' 123.123 2>/dev/null
$ printf '%d\n' "$int"
123
$ printf -v int '%d\n' abc 2>/dev/null
$ printf '%d\n' "$int"
0
$ printf -v int '%d\n' 1e10 2>/dev/null
$ printf '%d\n' "$int"
1
printf -v
tego można osiągnąć dzięki zastępowaniu poleceń:int="$(printf '%d' 123.123 2>/dev/null)"
bash
używasz wersji ?
Podobna sytuacja pojawiła się ostatnio podczas opracowywania skryptów bash do uruchamiania zarówno w środowiskach Linux, jak i OSX. Wynik jednej komendy w OSX zwrócił ciąg zawierający kod wyniku; tj " 0"
. Oczywiście nie udało się poprawnie przetestować w następującym przypadku:
if [[ $targetCnt != 0 ]]; then...
Rozwiązaniem było wymuszenie (tj. „Konwersja”) wyniku na liczbę całkowitą, podobną do odpowiedzi @ John1024 powyżej, aby działał zgodnie z oczekiwaniami:
targetCnt=$(($targetCnt + 0))
if [[ $targetCnt != 0 ]]; then...
==
itp. w [[
(również [
aka test
) zrobić porównanie ciągów. Istnieją różne operatory dla porównania arytmetyczne, np [[ $targetcnt -ne 0 ]]
; zobacz manpage (lub info) w wyrażeniach warunkowych. Aby przyciąć spacje konkretnie, możesz użyć niewymienionego [
rozszerzenia zmiennej, [ $targetcnt == 0 ]
aby uzyskać domyślne dzielenie słów (NIE zrobione w [[
), ale ogólnie takie podejście prowadzi do niebezpieczeństwa.
dbają o kody kolorów, nawet w trace ( -x
) nie będą się pojawiać, co by je rozdawało, to że ciąg, który ma być liczbą, jest zawijany w cudzysłów, bez względu na to, jak go wydrukujesz.
$((var+var))
nawet nie powiodły się choć jeśli ty echo
lub printf
obaj jesteście tymi samymi. Nie znam tej poprawki, ponieważ mogłem ją naprawić, wyłączając kody kolorów u źródła danych wyjściowych. Aby wykryć to w dziennikach śledzenia, zobaczysz przypisaną zmienną var='0'
, która powinna być po prostu taka, jaka powinna byćvar=0
sed
jeśli nie możesz go wyłączyć
printf "1 + %s\n" $1 won't do ?