Выполнение простой математики в командной строке с использованием функций bash: $ 1, деленное на $ 2 (возможно, с использованием bc)


33

Иногда мне нужно разделить одно число на другое. Было бы здорово, если бы я мог просто определить функцию bash для этого. До сих пор я вынужден использовать такие выражения, как

echo 'scale=25;65320/670' | bc

но было бы здорово, если бы я мог определить функцию .bashrc, которая выглядела бы как

divide () {
  bc -d $1 / $2
}

Ответы:


45

У меня есть удобная функция bash calc:

calc () {
    bc -l <<< "$@"
}

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

$ calc 65320/670
97.49253731343283582089

$ calc 65320*670
43764400

Вы можете изменить это, чтобы удовлетворить себя. Например:

divide() {
    bc -l <<< "$1/$2"
}

Примечание: <<< это строка здесь, которая подается в стандартную строкуbc . Вам не нужно призывать echo.


3
Я согласен, что он выглядит лучше без добавления дополнительного эха, но, поскольку он встроен в оболочку, он идет практически без дополнительных затрат. Что мешает мне использовать «<<<» в функциях оболочки, так это ограничение bash, в то время как дополнительное эхо позволяет использовать его в исходной оболочке bourne или ksh без изменений.
Татьяна Хойзер

@TatjanaHeuser ksh, 93-вариант, поддерживает здесь-строки.
Кусалананда

Чтобы присвоить переменную, я сделал это: foo = $ (bc -l <<< "(2 * 5) + 5")
thebiggestlebowski

20

Bash может в какой-то степени сам заниматься математикой. Это не полезно для точности, хотя, поскольку это округляет.

[user]$ echo $(( 10/5 ))
2

Но вы совершенно правы - функция bash будет простым ярлыком, и ваш пример в основном работает.

divide() {
  echo "scale=25;$1/$2" | bc
}

Добавьте это в свой .bashrc, и тогда вы сможете:

[user]$ divide 10 5
2.0000000000000000000000000

1
echo $((10 / 5))не нуждается в цитате.
пользователь неизвестен

1
Значительное раздражение: echo $((6383/7671)) даст вам ноль. Вы должны четко указать числа с плавающей запятой:echo $((6383.0/7671.0))
Шридхар Сарнобат

9

Вы, вероятно, знаете, что встроенный в Bash expr, как в

$ expr 60 / 5
12

который ограничен целыми числами и нуждается в пробелах между аргументами.

Что мешает вам определить функцию в соответствии с выражением эха, которое вы уже используете? Т.е.

 divide () {
   echo $1/$2 | bc
 }

1
просто невежество я не осознавал, что
смогу

7

Не совсем ответ на этот точный вопрос, но это может быть полезно знать. Используйте zsh;-)

% echo $((65320./670))
97.492537313432834

Я на самом деле искал этот вопрос, потому что я перешел на zsh и не смог использовать exprвстроенную
Steen Schütt

2

Если вы calcустановили в своей системе и вам не нравится округление, вы можете:

div() { calc "$1 / $2"; }

хм ... не удалось найти пакет Debian для 'calc'
ixtmixilix

Пакет называется apcalc (Arbitary Precision) ... Двоичный файл называетсяcalc
Peter.O

@ Peter.O Хорошо, в репозиториях Arch Linux это называется calc.

2

Грязный хак для малых значений и ограниченной точности без использования bc был бы, чтобы умножить знаменатель перед делением, чтобы получить точный результат.

Пример без точности:

echo $((13/7)) 
1

и с точностью до 2 цифр: умножьте на 100 и сдвиньте десятичную точку на 2 шага влево:

echo $((100*13/7)) | sed 's/..$/.&/'
1.85
echo $((100*13/7))%
185%

Это полезно только в том случае, если диапазон чисел известен ранее, а точность всегда одинакова. Избегать вызова bc и вызывать sed кажется не очень разумным.

Обратите внимание, что умножение значений может привести к ошибкам переполнения, но не очень рано:

echo $((1000000000*12345678901))
-6101065172709551616

Использование двойных скобок для оценки математических выражений не рекомендуется. Используйте: $[expression]вместо этого
laebshade

3
@laebshade: Я могу доказать, что ты не прав, все наоборот. Вот цитата из руководства bash:The old format $[expression] is deprecated and will be removed in upcoming versions of bash.
пользователь неизвестен


0

Вместо использования bc, вы можете использовать awk:

div() { awk -v p=$1 -v q=$2 'BEGIN{print p/q}'; }

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.