Є два випадки, коли мені здається :корисним:
Призначення змінної за замовчуванням
#!/bin/sh
# set VAR to "default value" if not already set in the environment
: "${VAR=default value}"
# print the value of the VAR variable. Note that POSIX says the behavior
# of echo is implementation defined if the first argument is '-n' or if any
# argument contains a '\', so use printf instead of echo.
printf '%s\n' "VAR=${VAR}"
Це зручний спосіб дозволити користувачам вашого сценарію оболонки змінювати налаштування без редагування сценарію. (Однак аргументи командного рядка є кращими, оскільки ви не ризикуєте несподіваною поведінкою, якщо у користувача випадково є змінна, яку ви використовуєте, в їх експортованому середовищі.) Ось як користувач замінить налаштування:
VAR="other value" ./script
${VAR=value}Синтаксис говорить набір VARдля valueякщо VARще не встановлено, а потім розширити до значення змінної. Оскільки нас ще не хвилює значення змінної, вона передається як аргумент команді no-op :для її викидання.
Незважаючи на те, що :це команда без операції, розширення виконується оболонкою (а не :командою!) Перед запуском :команди, так що присвоєння змінної все ще відбувається (якщо це можливо).
Також було б прийнятним trueзамість цього використовувати або якусь іншу команду :, але код стає важче читати, оскільки намір менш зрозумілий.
Наступний сценарій також працює:
#!/bin/sh
# print the value of the VAR variable. Note that POSIX says the behavior
# of echo is implementation defined if the first argument is '-n' or if any
# argument contains a '\', so use printf instead of echo.
printf '%s\n' "VAR=${VAR=default value}"
Але сказане вище набагато складніше. Якщо ${VAR}над цим printfрядком додано рядок, що використовує, розширення призначення за замовчуванням потрібно перемістити. Якщо розробник забуде перемістити це завдання, вводиться помилка.
Щось поставити в порожній умовний блок
Порожніх умовних блоків, як правило, слід уникати, але вони іноді корисні:
if some_condition; then
# todo: implement this block of code; for now do nothing.
# the colon below is a no-op to prevent syntax errors
:
fi
Деякі люди стверджують, що наявність порожнього істинного ifблоку може полегшити читання коду, ніж заперечення тесту. Наприклад:
if [ -f foo ] && bar || baz; then
:
else
do_something_here
fi
Можливо, простіше читати, ніж:
if ! [ -f foo ] || ! bar && ! baz; then
do_something_here
fi
Однак я вважаю, що існує кілька альтернативних підходів, які є кращими від порожнього справжнього блоку:
Поставте умову у функцію:
exotic_condition() { [ -f foo ] && bar || baz; }
if ! exotic_condition; then
do_something_here
fi
Помістіть умову всередині фігурних дужок (або круглих дужок, але в дужках породжений процес підзагортання, і будь-які зміни, внесені до середовища в підпакеті, не будуть видні за межами нижньої оболонки) перед тим, як заперечити:
if ! { [ -f foo ] && bar || baz; } then
do_something_here
fi
Використовуйте ||замість if:
[ -f foo ] && bar || baz || {
do_something_here
}
Я віддаю перевагу такому підходу, коли реакція є простим однолінійним, таким як умови затвердження:
log() { printf '%s\n' "$*"; }
error() { log "ERROR: $*" >&2; }
fatal() { error "$@"; exit 1; }
[ -f foo ] && bar || baz || fatal "condition not met"