3

В настоящее время я изучаю мир сценариев bash. Я знаю, что bash сам по себе не выполняет арифметику с плавающими целыми числами. Я провел некоторые исследования и обнаружил, что есть инструменты, которые могут помочь выполнить работу. Я решил использовать калькулятор bc Единственная проблема - это синтаксис. Я могу получить результаты, но не желаемым способом. Как я могу присвоить $N_RESULTS значение математической операции?

//I get arithmetic error with this syntax
DECI=128.17333
let "N_RESULTS = ($DECI - 1) / 10 + 1" | bc -l
echo $N_RESULTS

_

//I get correct results if do something like this
DECI=128.17333
echo "($DECI - 1) / 10 + 1" | bc -l

1 ответ1

2
N_RESULTS=$( echo "($DECI - 1) / 10 + 1" | bc -l )

Что let делает

Рассматривать:

let "N_RESULTS = ($DECI - 1) / 10 + 1" | bc -l

Этот трубопровод состоит из двух частей. Первым является команда let оболочки. Из-за | Символ, вывод команды let передается в стандартный поток команды bc . Хотя ' let способен выполнять целочисленную арифметику и может присваивать значения переменной, он не производит никакого вывода. Следовательно, даже если бы он работал правильно, он ничего не передал бы в bc .

Вот пример рабочей команды let :

$ let "result = (123 - 1) / 10 + 1"
$ echo $result
13

Однако, если бы мы предоставили аргумент с плавающей запятой, возникла бы ошибка:

$ let "result = (123.0 - 1) / 10 + 1"
bash: let: result = (123.0 - 1) / 10 + 1: syntax error: invalid arithmetic operator (error token is ".0 - 1) / 10 + 1")

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

Что делает bc

bc выполняет арифметику с плавающей запятой и может использоваться для назначения и управления переменными:

$ echo "result = (123.0123 - 1) / 10 + 1; print result" | bc -l
13.20123000000000000000

Тем не менее, обратите внимание, что вышесказанное само по себе не создает никаких переменных, которые можно использовать в оболочке. Определение result истекает, когда bc заканчивает обработку. Чтобы передать значение обратно в оболочку, нам нужно выполнить присвоение переменной оболочки, например:

$ result=$(echo "(123.0123 - 1) / 10 + 1" | bc -l )
$ echo $result
13.20123000000000000000

Конструкция $(...) называется подстановкой команд. Он запускает команду, в данном случае конвейер echo и bc, и помещает свой стандартный вывод в командную строку, где он назначается переменной result .

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

Что такое bc эквивалент для [[ $offset -lt $result ]]

Команды test оболочки, включая [ и [[ , создают полезный код завершения, который можно использовать в if , while и других контекстах, таких как && и || где коды выхода используются для определения потока программы. bc не подражает такому поведению. Он возвращает код выхода 0 для любого успешного расчета. Возвращает ненулевые коды выхода, если произошла ошибка. Приведенные ниже примеры показывают, как с помощью grep bc можно использовать для установки полезных кодов выхода.

В GNU bc реляционные выражения оцениваются в 1 для истины и 0 для ложных. Итак, чтобы проверить, меньше ли offset чем result , мы просто проверяем, возвращает ли bc 0 или 1 . Здесь grep используется для проверки вывода bc и установить соответствующий код возврата , который может быть использован в if в while или в других местах , где оболочка будет проверить код возврата. Например:

$ offset=1.25; result=1.33
$ echo "$offset < $result" | bc -l | grep -q 1 && echo yes || echo no
yes
$ offset=1.35
$ echo "$offset < $result" | bc -l | grep -q 1 && echo yes || echo no
no

Под не GNU bc можно сделать то же самое, но формально, if требуется оператор:

echo "if ($offset < $result) print 1 else print 0 " | bc -l | grep -q 1 && echo yes || echo no

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .