Який сенс баш-нульового оператора “:”, двокрапка?


13

Який сенс оператора "null" у сценарії BASH? Я розумію, що він використовується як заповнювач місця після ifкоманди, коли вам нічого сказати, але потрібна команда, яка дозволяє програмі правильно працювати. Але яка загальна користь для цього? Коли ви використовуєте його? Коли має сенс його використовувати?



1
Причина, яку ви цитуєте, досить важлива. Навіщо потрібно більше?
тердон

Відповіді:


16

Іноді корисно дозволити виникнення побічних ефектів розширення параметрів.

Наприклад, встановлення значення за замовчуванням

read -p "Enter your name: " name
: ${name:=John Doe}  # if the user entered an empty string
echo "$name"

2
Чи можете ви пояснити символ за символом, як працює другий рядок?
Руслан

Про :команду та розширення параметрів читайте у посібнику з bash.
glenn jackman

4
Щоб окреслити те, на що посилається @glennjackman, другий рядок викликає команду null:, і ${name:="John Doe"}буде розширено, викликаючи призначення, оскільки воно читається як аргумент:. Без: оболонка спробує запустити "John Doe" як команду, або значення, $nameякщо воно вже встановлено
imkendal

13

Ви також можете використовувати його для нескінченних циклів:

while : ; do 
   # ....
done

4
Але, можливо, while trueце читабельніше, тому що (а) він використовує менше розділових знаків, і (б) він більше схожий на мови, що походять з С.
wchargin

9

Ви можете використовувати його для створення файлу без запуску програми ::

: > /path/to/file

Це нескінченно швидше, ніж touch /path/to/file (оскільки не вимагає запуску touchпрограми) і може бути незначно більш портативним, ніж просто

> /path/to/file

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

if { : >> /path/to/file;} 2> /dev/null
then
    echo "writeable"
else
    echo "write permission denied"
fi

хоча це також, як правило, можна зробити без :. Застереження:

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

(Дивіться пов'язане запитання з причин, чому це надійніше, ніж if [ -w /path/to/file ].)


5

Зворотній шлях, в Unix V6 та Thompson Shell, :фактично був використаний як частина gotoзаяви. Згідно з посібником , він спочатку з'явився у версії 3 Unix:

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

У наш час bashвін використовується як неоперативний оператор, що повертає успіх. Дійсно, якщо ви подивитесь на вихідний код , ви побачите, що обидва trueі :використовуєте одну і ту ж функцію int colon_builtin(), під ним. Немає :вбудованої команди, а /bin/trueнасправді досить велика команда для того, що вона робить.

:може бути використаний де завгодно true, наприклад, у command_that_can_fail || true, хоча це може заплутати неекспертів. Детальніше про це читайте тут .


3

Ви можете використовувати його на позитивному тесті ifкоманди, коли ви хочете зробити щось з негативної сторони. Наприклад:

if [[ True == False ]]; then
    :
else
    echo "true <> flase"
fi

Без :bash генерується синтаксична помилка.

Це спрощений приклад. Як правило, ви використовуєте таку техніку для попереднього кодування, коли ви ще не написали цей кодовий сегмент і вам просто потрібно щось, що не створює помилок.


Хороша відповідь, хоча спочатку це може бути не видно, що це найбільш корисно для фактичної команди в тестовому стані, наприклад, if pgrep firefox >/dev/null ; then : ; else echo "Firefox not running"; fiвиявиться помилка, лише якщо firefox не працює. Іншими словами, коли вам потрібно щось робити лише тоді, коли в команді є помилка. У чомусь це рівнозначно pgrep firefox || echo "Firefox not running", хоча і читабельніше і дозволяє більше команд
Сергій Колодяжний

0

Я просто використовував його в сценарії з командами SSH, щоб скрипт не помилявся.

У цьому випадку я хочу перевірити, чи може користувач підключитися до набору серверів. Якщо з'єднання в порядку, віддалений хост відлунне ОК. Якщо з'єднання не вдалося, SSH відповість на помилку. Однак я хочу, щоб мій сценарій вийшов з 0, а не значення команди SSH, якщо він не вдався. Отже, по суті, я вловлюю помилку SSH, посилаючи її ||на команду null :. Виглядає так:

#!/bin/bash
for i in $(cat servers.txt); do
    echo -n "$i "; 
    ssh user@${i} 'echo OK' || :; 
done

Таким чином я отримую вихід із SSH, але не код помилки:

....
swl06 ok
swl07 ok
swl08 Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
swl09 ok
swl10 Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
....
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.