Яка найкраща практика представляти булеве значення в сценарії оболонки?


15

Я знаю, що булеві значення є bash, але я ніколи не бачу, щоб вони використовувалися ніде.

Я хочу написати обгортку для деякої часто шуканої інформації на моїй машині, наприклад, це конкретний USB-накопичувач, вставлений / встановлений.

Що було б найкращою практикою для досягнення цього?

  • Рядок?

    drive_xyz_available=true
  • Число (0 для істинного, ≠ 0 для помилкового)?

    drive_xyz_available=0    # evaluates to true
  • Функція?

    drive_xyz_available() { 
        if available_magic; then 
                return 0 
        else 
                return 1 
        fi
    }
    

Мене найбільше цікавить питання, що можна було б очікувати від інших людей, які хотіли б використовувати обгортку. Чи очікують вони булевого значення, команди на зразок змінної або функції для виклику?

З точки зору безпеки, я вважаю, що другий варіант є найбезпечнішим, але я хотів би почути ваш досвід.


3
help true ; help false ; help exit
Костас

3
@Costas Ви б проти зауважити?
Мінікс

Відповіді:


2
bool(){ return "$((!${#1}))"; }

if bool "$var"
then : do true
else : do false

Просто встановіть змінну на що-небудь, але не-null, щоб вищезазначене працювало, хоча [ -n "$var" ]було б коротше, якби не настільки очевидно.

Загалом, коли скрипт інтерпретує змінну середовища як істинну, так і хибну, вона буде інтерпретувати будь-яке значення як істинне (а іноді використовувати вказане значення для налаштування якоїсь опції), або інше нульове значення як хибне.

Вищезазначене повертає булеве !notзначення ліцензії першого аргументу - якщо аргумент містить будь-яку кількість символів, крім 0, він повертає 0, інакше, якщо символів немає, він повертається 1. Це те саме тест, з яким ви можете виконати [ -n "$var" ], в основному , але це просто вбудовує його в маленьку функцію з назвою bool().

Зазвичай це працює змінна прапор . Наприклад:

[ -d "$dir" ] || dir=

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

for set in yes ''
do echo "${set:-unset or null}"
done

... яка б надрукувала ...

yes
unset or null

Звичайно, можна зробити і навпаки, :+але це може коли-небудь дати вам попередньо встановлений замовчування або взагалі нічого, тоді як вищевказана форма може дати вам значення або значення за замовчуванням.

І так щодо трьох варіантів - кожен може працювати, залежно від того, як ви вирішите його здійснити. Повернення функції - це самотестування, але, якщо це повернення потребує збереження з будь-якої причини, його потрібно буде помістити в змінну. Це залежить від випадку використання - є булевим значенням, яке ви хочете оцінити тест один раз і готовий тип? Якщо так, виконайте функцію, інакше будь-який з двох інших, ймовірно, необхідний.


1
Я не думаю, що ти відповідаєш на моє запитання. Я не запитую, як булеви можуть бути використані в сценарії оболонки, але який спосіб є найпоширенішим і на який очікував би інший користувач. Якщо моє питання незрозуміле, я би радий його відредагувати. Також було б непоганим коротке пояснення того, що робить ваша відповідь. Дякую.
Мінікс

@Minix Краще?
mikeserv

Я взагалі призначити trueабо falseзмінної, ви можете зробитиif $variable; then ...
wurtel

@wurtel - що покладається на замовчування $IFS- і якщо значення var може містити будь-який ввід користувача, то також на щастя. Якщо значення невідомо для початку, то його тестування мало потрібно. Більш безпечно це можна робити if ${var:+":"} false; thenпід час роботи w / boolean null / not null значень. Але це рідко корисніше ніж[ -n "$var" ] &&
mikeserv

Якщо я запускаю свій скрипт, variable=falseа потім встановлюю його як істинне відповідно до будь-яких умов (так само, як я б при використанні змінної в С), тоді немає жодної проблеми, яка ваша одержимість різними значеннями IFS та випадковими значеннями змінної тощо. .
wurtel

4

У bashкожній змінній по суті є рядок (або масив або функція, але поговоримо тут про регулярні змінні).

Умови аналізуються на основі повернених значень тестових команд - повернене значення не є змінною, це вихідний стан. Коли ви оцінюєте if [ ... ]чи if [[ ]]або що- if grep somethingнебудь подібне, значення повернення 0 (не рядок 0, а статус виходу 0 = успіх) означає істинне, а решта означає помилкове (так, прямо протилежне тому, до чого ви звикли в складених мовах програмування, але оскільки існує один спосіб досягти успіху та багато способів невдачі, і очікуваний результат виконання зазвичай є успіхом, 0 використовується як найпоширеніший результат за замовчуванням, якщо нічого не виходить). Це дуже корисно, тому що будь-який двійковий файл може бути використаний як тест - якщо він не працює, він помилковий, інакше це правда.

trueі falseпрограми (як правило, переосмислені вбудованими) - це просто корисні маленькі програми, які нічого не роблять - trueвдається нічого не робити, і завершує роботу з 0, при falseцьому намагається нічого не робити і "провалюється", виходячи з 1. Звучить безглуздо, але це дуже зручно для сценаріїв.

Що стосується того, як передати правдивість навколо, то вирішувати вам. Досить звичайно просто використовувати "y" або "так" для правди і використовувати if [ x"$variable" = x"yes" ](додається рядок манекена, xтому що, якщо $variableтрапляється нульова довжина, це захищає від створення неправдивої команди, if [ = "yes" ]яка не розбирає). Також може бути корисним просто використовувати порожню рядок для помилкової та використовувати [ -z "$variable ]для перевірки, чи вона нульової довжини (або, -nщоб вона не була нульовою ).

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


У вашому випадку ви хочете функцію, яка буде діяти як будь-яка інша команда (тому поверніть 0 на успіх), тому ваш останній варіант здається правильним вибором.

Крім того, вам може навіть не знадобитися returnзаява. Якщо функція досить проста, ви можете використовувати той факт, що вона просто повертає статус останньої виконаної команди у функції. Тож ваша функція може бути просто

drive_xyz_available() {
   [ -e /dev/disk/by-uuid/whatever ]
}

якщо ви перевіряєте наявність вузла пристрою (чи grep, /proc/mountsщоб перевірити, чи він встановлений?).


Це дуже приємне резюме, дякую, що знайшли час, щоб його написати. Чи можу я зробити висновок із вашого останнього абзацу, що ви вважаєте варіант drive_xyz_available()найпоширенішим?
Мінікс

Чи можете ви навести кілька прикладів для загальної y = trueсправи? На мій досвід, більшість скриптів обгортки перевіряють наявність будь-якого недійсного значення, щоб вважати його істинним - принаймні, коли йдеться про інтерпретовані змінні середовища. В іншому випадку вони взагалі ігнорують автомобілі.
mikeserv

3
Рядок манекена для ifтесту не потрібен, якщо вказана змінна; if [ "$variable" = "yes" ]працює добре, навіть якщо $ змінної не встановлено.
Даніель Куллманн

-2

В основному будь-яке число, яке не 0, є істинним, а 0 - хибним. Причина повернення значень як 0 для успішного закінчення сценарію або будь-якого іншого числа для виявлення помилок різного типу.

$? поверне код виходу попередньої команди / виконуваного файлу, досягаючи 0 успіху, а будь-який інший номер - помилка, яка була повернута.

Тому я використовував би цей метод для істинного / хибного. if (( ! $? ));then OK;else NOOK;fi


Тоді я напишу його для останнього варіанту. Дякую.
Мінікс

5
Ненульове число фактично є помилковим, а нуль - істинним. Подивіться на вихід true; echo $?та false; echo $?.
Руслан

@Ruslan. Ви перевірили вихід моєї команди? Я думаю, ти цього не зробив, інакше ти б не заявив, що робив. 0 - помилково, будь-яке інше число є істинним, причина відкидати !результат, щоб він був ІСТИНИМ. Результат команди буде 0, коли він закінчився правильно, що не означає, що 0 є істинним. Слово trueможе бути 0, але 0 ніколи не відповідає дійсності, як це ifдемонструє умова.
YoMismo

Це те саме, що говорити, що в C / C ++, 0це trueтому if(!x){True();}else{False();}, що подзвонить, True()коли x==0. Але правильної перевірки було б не !x, а скоріше !!x.
Руслан

Ви помиляєтесь waaaaaaay Я не кажу про те, що і в якому наказі є все, що ви пишете після того, як ifя просто констатую факт, що тут (в bash, або ksh, або tsh, або ....), як у C / C ++ a 0 - НЕЗАЛЕЖНА, будь-яка інше число - ПРАВИЛЬНЕ, як ви можете прочитати за наступним посиланням, початкові впровадження C не надавали булевого типу, визначаючись як ints, де 0 було FALSE, а 1 TRUE en.wikipedia.org/wiki/Boolean_data_type .
YoMismo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.