как добавить (вычесть и т. д.) два числа с помощью bash?

90

Я могу читать цифры и операции с:

echo "First number please"
read num1
echo "Second number please"
read num2
echo "Operation?"
read op

но тогда все мои попытки добавить цифры провалились:

case "$op" in
  "+")
    echo num1+num2;;
  "-")
    echo `num1-num2`;;
esac

Бегать:

First number please
1
Second mumber please
2
Operation?
+

Выход:

num1+num2

...или же...

echo $num1+$num2;;

# results in: 1+2    

...или же...

echo `$num1`+`$num2`;;

# results in: ...line 9: 1: command not found

Похоже, что я получаю строки все еще возможно, когда я пытаюсь добавить добавить ("2 + 2" вместо "4").

Майкл Даррант
источник
5
Я отредактировал ваш заголовок, потому что это хороший общий вопрос, и если бы вы сузили контекст, вы бы поняли, что это не имеет ничего общего ни с caseчем, кроме одной строки:, echo $num+$numпоскольку это точно воспроизведет проблему . Идея минимизации контекста в вопросах программирования объясняется здесь: sscce.org
goldilocks
2
+1 Привет, златовласка, да, это стало ясно мне потом, но да, я полностью согласен с твоей аргументацией, и да, чем конкретнее и «единичнее» вопрос, тем лучше. Я приветствую ваши правки :) Спасибо :)
Майкл Даррант

Ответы:

117

Арифметика в оболочках POSIX выполняется с $двойными скобками (( )):

echo "$(($num1+$num2))"

Вы можете назначить из этого (без echo):

num1="$(($num1+$num2))"

Также есть expr:

expr $num1 + $num2

В сценариях $(())предпочтительнее, поскольку он избегает форка / выполнения для exprкоманды.

лютик золотистый
источник
Или даже напрямую, echo $(($num1$op$num2))без участия case.
manatwork
Здесь нет caseпричастности.
Златовласка
1
Нет, но вы использовали литерал +, поэтому caseдля обработки вычитания потребуется внешняя сторона.
manatwork
1
@manatwork: Вы имеете в виду исключение caseиз кода OP с echo $(($num1$op$num2))- это будет работать, но использование caseболее надежно, поскольку вы можете обрабатывать ошибки по умолчанию *.
Златовласка
+1 к вам обоим. Я использовал случай (возможно, не показывал его с самого начала), но, как вы оба поняли, проблема была не в этом деле.
Майкл Даррант
13

Существующий ответ - чистый bash, поэтому он будет быстрее этого, но он может обрабатывать только целые числа. Если вам нужно обрабатывать поплавки, вы должны использовать внешнюю программу bc.

$ echo 'scale=4;3.1415+9.99' | bc
13.1315

scale=4Говорит bcиспользовать четыре знака после запятой. Смотрите man bcдля получения дополнительной информации.

evilsoup
источник
Обратите внимание , что в то время bashне поддерживает с плавающей точкой арифметика с $((...)), много снарядов ( ksh93, zsh, yashпо крайней мере) делать. Преимущество bcзаключается в том, что он поддерживает произвольную точность, в то время как арифметика оболочки ограничена doubleтипом процессора . Обратите внимание, что вам не нужно устанавливать scaleздесь. Для дополнений scaleпараметр не используется. Шкала 3.1415+9.99будет получена из шкалы операндов (здесь 4).
Стефан Шазелас
Как сделать математику, если одно значение 450является десятичным, а другое хранится в переменной $mynumber? Например, 450-$mynumber.
Сигур
@Sigur echo "450-$mynumber" | bcдолжен это сделать. Если вы хотите, чтобы переменная расширялась, вы должны использовать двойные кавычки, а не одинарные.
evilsoup
@evilsoup, теперь это работает как шарм. Благодарю.
Сигур
computedval=$(echo 'scale=10;var1-var2' | bc)не работает и не работаетcomputedval=$(echo 'scale=10;$var1-$var2' | bc)
StatsSorceress
5
echo `expr $a + $b`   
echo `expr $a - $b`   
echo `expr $a \* $b`   
echo `expr $a / $b`   

Обратите внимание, что \перед *(для умножения) все выражение должно быть в обратных кавычках `.

Himani
источник
1
exprне является обязательным, и никогда не требуется захватывать стандартный вывод команды, просто чтобы записать ее обратно в стандартный вывод.
Chepner
1

Вы также можете использовать $[ ... ]структуру. В этом случае мы используем встроенный механизм Bash, который быстрее и немного удобнее в использовании. Поскольку мы знаем, что все между $ [и] рассматривается как выражение, нам не нужно ставить переменные перед $. Точно так же нам не нужно защищать себя *от того, чтобы рассматривать это как шаблон.

num1=2
num2=3
echo $[num1 + num2]
5
джедай
источник
0

Судя по последовательности входных данных, которые вы запрашиваете у пользователя, кажется, что вы используете обратную польскую запись.

echo "First number please"
read num1
echo "Second number please"
read num2
echo "Operation?"
read op

Вы можете лучше просто использовать dc(настольный калькулятор), так как это то, для чего оно.

DESCRIPTION
       Dc is a reverse-polish desk calculator which supports unlimited pre-
       cision arithmetic.

Пример сеанса с использованием dc:

$ dc
1 2 + p    # This part is typed; the result comes next.
3
q  # This is also typed.
$

Или не в интерактивном режиме:

$ dc -e '1 2 + p'
3
$
Wildcard
источник