Намагаючись зрозуміти, як перетворити аргумент у ціле число, щоб виконати арифметику, а потім роздрукувати його, скажімо для addOne.sh
:
echo $1 + 1
>>sh addOne.sh 1
prints 1 + 1
Намагаючись зрозуміти, як перетворити аргумент у ціле число, щоб виконати арифметику, а потім роздрукувати його, скажімо для addOne.sh
:
echo $1 + 1
>>sh addOne.sh 1
prints 1 + 1
Відповіді:
У bash, один не "перетворює аргумент у ціле число для виконання арифметики". У bash змінні трактуються як цілі чи строкові в залежності від контексту.
Для виконання арифметики слід викликати оператора арифметичного розширення $((...))
. Наприклад:
$ a=2
$ echo "$a + 1"
2 + 1
$ echo "$(($a + 1))"
3
або загалом кращі:
$ echo "$((a + 1))"
3
Ви повинні знати, що bash (на відміну від ksh93, zsh або yash) виконує лише цілу арифметику. Якщо у вас є номери з плаваючою комою (цифри з десятковістю), то є інші інструменти для надання допомоги. Наприклад, використовуйте 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
Або ви можете використовувати оболонку з арифметичною підтримкою з плаваючою комою замість bash:
zsh> echo $((3.14 + 1))
4.14
У bash
, ви можете виконати перетворення з будь-якого в ціле число, використовуючи printf -v :
printf -v int '%d\n' "$1" 2>/dev/null
Плаваюче число буде перетворене на ціле число, тоді як все не буде схоже на число, яке буде перетворене на 0. Експоненція буде усічена на число e
Приклад:
$ 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
цього можна домогтися заміни команд:int="$(printf '%d' 123.123 2>/dev/null)"
bash
ви використовували?
Аналогічна ситуація виникла нещодавно при розробці bash-скриптів для роботи як в Linux, так і в OSX. Результат однієї команди в OSX повернув рядок, що містить код результату; тобто " 0"
. Звичайно, це не вдалося перевірити правильно у наступному випадку:
if [[ $targetCnt != 0 ]]; then...
Рішення полягало в тому, щоб примусити (тобто «перетворити») результат на ціле число, подібне до того, на що @ John1024 відповів вище, щоб він працював так, як очікувалося:
targetCnt=$(($targetCnt + 0))
if [[ $targetCnt != 0 ]]; then...
==
і т.д. в [[
(також [
aka test
) робити порівняння рядків. Існують різні оператори для арифметичного порівняння, наприклад [[ $targetcnt -ne 0 ]]
; див. сторінку (або інформацію) у розділі Умовні вирази. Щоб спеціально обрізати пробіли, ви можете використовувати [
розширення без [ $targetcnt == 0 ]
змін, що цитуються, щоб отримати розбивання слів за замовчуванням (НЕ робиться в [[
), але загалом такий підхід приводить вас до небезпеки.
дбайте про кольори кольорів, навіть у слідах ( -x
) вони не з’являться. Що б це не було, це те, що рядок, який повинен бути числом, загорнутий у лапки незалежно від того, як ви їх друкуєте.
$((var+var))
не вдатися навіть хоча якщо ви echo
або printf
обидва вари, вони однакові. Я не знаю виправлення, оскільки мені вдалося виправити його лише відключивши кольорові коди у джерелі виводу. Щоб помітити його в журналах слідів, ви побачите змінну, що порушує право, присвоєну так, var='0'
як це просто повинно бутиvar=0
sed
якщо ви не можете вимкнути його
printf "1 + %s\n" $1 won't do ?