Як я можу зробити поділ зі змінними в оболонці Linux?


136

Коли я запускаю команди в своїй оболонці, як показано нижче, вона повертає expr: non-integer argumentпомилку. Може хтось, будь ласка, пояснить це мені?

$ x=20
$ y=5
$ expr x / y 
expr: non-integer argument

4
@ShivanRaptor Хоча можна стверджувати, що питання є питанням RTFM, це, безумовно, дійсне питання програмування оболонки. Це також розумне питання для когось із мов, які не потребують перенаправлення (наприклад, Ruby або JavaScript). Його слід залишити відкритим.
Тодд А. Джейкобс

6
@ShivanRaptor Ні, це тут на тему. Йдеться про програмування в Bash. Unix / Linux - це насамперед для використання системи, а не для програмування. Тепер сценарій оболонки охоплює межу між програмуванням та використанням системи, тому це може бути обговорене на будь-якому сайті. Якби виникло питання про те, "як мені встановити мережу", це однозначно належало б на Unix / Linux. Якби мова йшла про інтерактивні палітурки клавіш на Bash, це теж би там належало. Але питання щодо сценаріїв оболонок, безумовно, є на темі як тут, так і там.
Брайан Кемпбелл

Дивіться мою відповідь тут, що ілюструє віднімання та поділ змінних $ BASH, використовуючи виклик Python з оболонки (для перетворення int в плавати ...): stackoverflow.com/questions/8385627/…
Victoria Stuart

Відповіді:


195

Ці змінні є змінними оболонок. Щоб розширити їх як параметри до іншої програми ( тобто expr ), вам потрібно використовувати $префікс:

expr $x / $y

Причина, на яку він скаржився, полягає в тому, що він вважав, що ви намагаєтесь працювати з алфавітними символами ( тобто не цілими числами)

Якщо ви використовуєте оболонку Bash, ви можете досягти такого ж результату, використовуючи синтаксис виразів:

echo $((x / y))

Або:

z=$((x / y))
echo $z

1
Ви можете дізнатися багато, прочитавши man-сторінку для bash. Введіть man bashпідказку ( qдля виходу)
неділю

62
Десь на цій сторінці слід зазначити, що більшість (якщо не всі) оболонок GNU / Linux виконують лише цілі операції .
Skippy le Grand Gourou

35

Я вважаю, що це вже згадувалося в інших темах:

calc(){ awk "BEGIN { print "$*" }"; }

тоді ви можете просто ввести:

calc 7.5/3.2
  2.34375

У вашому випадку це буде:

x=20; y=3;
calc $x/$y

або якщо ви хочете, додайте це як окремий сценарій і зробіть його доступним у $ PATH, щоб ви завжди мали його у вашій локальній оболонці:

#!/bin/bash
calc(){ awk "BEGIN { print $* }"; }

4
Ви також можете використовуватиecho '1 / 3' | bc -l
Євген

19

Чому б не використовувати let; Мені це набагато легше. Ось приклад, який вам може бути корисним:

start=`date +%s`
# ... do something that takes a while ...
sleep 71

end=`date +%s`
let deltatime=end-start
let hours=deltatime/3600
let minutes=(deltatime/60)%60
let seconds=deltatime%60
printf "Time spent: %d:%02d:%02d\n" $hours $minutes $seconds

Ще один простий приклад - обчислити кількість днів з 1970 року:

let days=$(date +%s)/86400

15

Посилання на змінну діаграми вимагає розширення параметрів

Оболонка за замовчуванням у більшості дистрибутивів Linux - Bash. У Bash змінні повинні використовувати префікс знака долара для розширення параметра . Наприклад:

x=20
y=5
expr $x / $y

Звичайно, Bash також має арифметичні оператори та спеціальний синтаксис арифметичного розширення , тому немає необхідності викликати бінарний файл expr як окремий процес. Ви можете дозволити оболонці виконувати всю роботу так:

x=20; y=5
echo $((x / y))

Див. Арифметичне розширення та арифметику оболонки в Довідковому посібнику Баша для всіх деталей горі.
Тодд А. Джейкобс

1
Це не має нічого спільного з перенаправленням, а інтерполяцією, і exprце перешкоджає 2013 р.
Жилль Кінот

@sputnick Ви явно розгублені. Будь ласка, зверніться до словника. Дивіться повагу та інтерполяцію .
Тодд А. Джейкобс

1
Краще слово - це розширення , але не перенаправлення . dereferencing використовується при використанні покажчиків , це не так, це просто прості змінні.
Жиль Кінот

1
@Prashant: tldp, як відомо, не є хорошим орієнтиром у світі баш.
Жиль Кінот

1

припустимо

x=50
y=5

тоді

z=$((x/y))

це буде працювати належним чином. Але якщо ви хочете використовувати / оператора в операторах випадків, він не може його вирішити. введіть тут код У цьому випадку використовуйте прості рядки, такі як div або devide або щось інше. Дивіться код


Це неправильно. /прекрасно працює як оболонка корпусу. Те, що не працює, - це використовувати *для множення, не цитуючи це, що може бути тим, що ви насправді зробили; це призводить до того, що він ефективно перекриває всі наступні пункти у справі, які у вашому прикладі - "розділити" та "модуль"
dave_thompson_085,

0

Щоб отримати цифри після десяткових знаків, ви можете зробити це:

read num1 num2
div=`echo $num1 / $num2 |bc -l`
echo $div
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.