Проведення математики в командному рядку за допомогою функцій 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"
}

Примітка: <<< це рядок тут, який подається в stdin bc. Вам не потрібно викликати echo.


3
Я погоджуюсь, що це виглядає краще без додаткового відлуння, але оскільки він є вбудованим в оболонку, він не має додаткових витрат. Що не дає мені використовувати "<<<" у функціях оболонки - це обмеження на bash, тоді як додаткове відлуння дозволяє використовувати його в оригінальній оболонці bourne або ksh без змін.
Тетяна Хейзер

ksh93-варіант @TatjanaHeuser підтримує тут-рядки.
Kusalananda

Щоб призначити змінну, я зробив це: foo = $ (bc -l <<< "(2 * 5) + 5")
thebiggestlebowski

20

Баш може певною мірою робити математику сам. Однак це не корисно для точності, оскільки вона округляє.

[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
просто незнання. Я не усвідомлював, що можу змусити його працювати так ...
ixtmixilix

7

Насправді це не відповідь на це точне запитання, але це може бути добре знати. Використовуйте zsh;-)

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

Я насправді шукав це питання, тому що я перейшов на zsh і не міг використовувати exprвбудований bash , тому добре відповідь незалежно :)
Steen Schütt

2

Якщо у вас calcвстановлена ​​система і вам не подобається округлення, ви можете:

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

хм ... не вдалося знайти жодного пакета debian для 'calc'
ixtmixilix

Пакет називається apcalc (Арбітражна точність) ... Двійковий називаєтьсяcalc
Пітер.О

@ Peter.O Гаразд, в репортажі Arch Linux це називається calc.

2

Брудний хак для малих значень і обмеженої точності без використання bc - це, помноживши номінатор перед діленням, отримати точний результат.

Приклад без точності:

echo $((13/7)) 
1

і з двозначною точністю: помножте на 100 і рухайте десяткову точку на 2 кроки вліво:

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

Це корисно лише в тому випадку, якщо діапазон чисел відомий раніше, а точність завжди однакова. Уникати дзвінків на bc , а дзвонити sed видається не дуже розумним.

Зауважте, що множення значень може призвести до помилок переповнення, але не дуже рано:

echo $((1000000000*12345678901))
-6101065172709551616

Використання подвійних дужок для оцінки математичних виразів застаріле. Використовуйте: $[expression]натомість
маячок

3
@laebshade: Я можу довести, що ви помиляєтесь, правда навпаки. Ось цитування керівництва bash:The old format $[expression] is deprecated and will be removed in upcoming versions of bash.
користувач невідомий

Також обговорювались тут ,  тут  і  тут .
G-Man каже "Відновити Моніку"

0

Замість використання bc ви можете використовувати awk:

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

-4
echo Division
efgh=$num1/$num2
remainder=$num1%num2
echo $num1 "/" $num2 "=" $efgh.$remainder
echo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.