Какая команда означает «ничего не делать» в условном выражении в Bash?

181

Иногда при создании условий мне нужен код, который ничего не делает, например, здесь я хочу, чтобы Bash ничего не делал, если значение $aбольше 10, выведите «1», если $aменьше 5, в противном случае выведите «2»:

if [ "$a" -ge 10 ]
then
elif [ "$a" -le 5 ]
then
    echo "1"
else
    echo "2"
fi

Это делает ошибку, хотя. Есть ли команда, которая ничего не будет делать, а также не замедлит мой сценарий?

Деревня
источник

Ответы:

341

Командой no-op в оболочке является :(двоеточие).

if [ "$a" -ge 10 ]
then
    :
elif [ "$a" -le 5 ]
then
    echo "1"
else
    echo "2"
fi

Из руководства по bash :

:(двоеточие)
Ничего не делайте, кроме расширения аргументов и выполнения перенаправлений. Статус возврата равен нулю.

Barmar
источник
3
@ SaintHax Нет, это не работает true. Он встроен в оболочку и ничего не делает.
Бармар
1
это встроенная оболочка (вы правы), она возвращает true (статус 0), как и true, и ее труднее читать. Bash - это язык DevOps, и если :он написан кем-то из моей команды, я бы попросил его изменить его.
SaintHax
3
@SaintHax Если бы кто-то использовал trueв безусловном контексте, я бы попросил его изменить его. if trueхорошо, then trueкажется, неправильно.
Бармар
1
Конечно, вы можете просто переписать код для использования if ! condition; then do something; fiвместо if condition; then :; else do something; fi.
Бармар
Я согласен с тобой. Этот пример может быть написан, если / elif / else использует составные условия и будет лучше.
SaintHax
38

Вы можете, вероятно, просто использовать trueкоманду:

if [ "$a" -ge 10 ]; then
    true
elif [ "$a" -le 5 ]; then
    echo "1"
else
    echo "2"
fi

Альтернативой в вашем примере (но не везде) является переупорядочение if / else:

if [ "$a" -le 5 ]; then
    echo "1"
elif [ "$a" -lt 10 ]; then
    echo "2"
fi
Flimzy
источник
8
Если вы не тестируете оба результата trueи falseфактически не выполняете никаких действий в отношении сценария, но в принципе они могут использовать некоторые оболочки, которые принимают этот синтаксис, так что, возможно, :это лучше.
dmckee --- котенок экс-модератора
3
Вопрос помечен как bash. В bash есть trueи falseвстроенные модули. Для более старых оболочек, true, falseи даже :может быть внешние команды (хотя вы, вероятно , увидеть последний только в очень старых оболочек).
Кит Томпсон
6
Я предпочитаю :просто, потому что это более ясно, что цель
Freedom_Ben
9

Хотя я не отвечаю на первоначальный вопрос о команде no-op, многие (если не большинство) проблем, когда можно подумать, что « в этой ветке я ничего не должен делать », можно обойти, просто перестроив логику так, чтобы эта ветка победила не происходит

Я пытаюсь дать общее правило, используя пример ОП

ничего не делать, если $ a больше «10», выведите «1», если $ a меньше «5», в противном случае выведите «2»

мы должны избегать ветвления, где $aполучается больше 10, так что $a < 10в качестве общего условия можно применять любое другое, следующее условие.

В общих чертах, когда вы говорите , ничего не делать , когда X , то перефразировать как избежать ветви , где X . Обычно вы можете избежать этого, просто отрицая X и применяя его ко всем остальным условиям.

Таким образом, пример OP с примененным правилом может быть изменен следующим образом:

if [ "$a" -lt 10 ] && [ "$a" -le 5 ]
then
    echo "1"
elif [ "$a" -lt 10 ]
then
    echo "2"
fi

Просто вариация из вышеперечисленного, заключающая в себе все в $a < 10состоянии:

if [ "$a" -lt 10 ]
then
    if [ "$a" -le 5 ]
    then
        echo "1"
    else
        echo "2"
    fi
fi

(Для этого конкретного примера реструктуризация @Flimzys, безусловно, лучше, но я хотел бы дать общее правило для всех людей, ищущих, как ничего не делать.)

KeyNone
источник
5
Одна из причин, по которой кто-то может захотеть запретить работу, заключается в том, чтобы изначально структурировать код с идеей, что кто-то добавит «добавить что-то сюда позже» без непреднамеренных побочных эффектов. Например, если кто-то помещает if-then-else-fi в .bashrc, то, если вы echo "put stuff here"его поместите, он прервет некоторые виды использования без входа в систему (например, scp прекратит работу), и только пробелы / комментарии вызовут ошибку времени выполнения.
Апоид