
Есть ли разница в bash или предпочтительное использование отрицания оператора?
if ! [[ -z "${var}" ]]; then
do_something
fi
Против
if [[ ! -z "${var}" ]]; then
do_something
fi
решение1
! [[ expression ]]
Это будет верно, если весь тест вернет false.
[[ ! expression ]]
Это будет верно, если отдельное выражение вернет ложь.
Поскольку тест может быть составным выражением, это может быть очень по-разному. Например:
$ [[ ! 0 -eq 1 || 1 -eq 1 ]] && echo yes || echo no
yes
$ ! [[ 0 -eq 1 || 1 -eq 1 ]] && echo yes || echo no
no
Лично я предпочитаю использовать отрицание внутри тестовой конструкции, где это применимо, но и снаружи оно тоже прекрасно подходит, в зависимости от ваших намерений.
решение2
А ! cmd
на самом деле этотрубка, и !
отрицает код выходавесьтрубка.
Из man bash:
Конвейеры Конвейер — это последовательность из одной или нескольких команд, разделенных одним из операторов управления | или |&. Формат конвейера:
[time [-p]] [ ! ] command [ [|||&] command2 ... ]
...
Если зарезервированное слово ! предшествует конвейеру, статус выхода этого конвейера является логическим отрицанием статуса выхода, как описано выше. Оболочка ждет завершения всех команд в конвейере, прежде чем возвращать значение.
В этом смысле:
! [[ 2 -eq 2 ]]
Является отрицанием ( !
) кода выхода всего [[
(после того, как все это было выполнено). Таким образом, это имеет код выхода 0:
! [[ 2 -eq 2 && 3 -eq 4 ]]
Однако
А [[ ! ]]
есть аСоставная команда(не труба). Из man bash:
Составные команды
...
[[ выражение ]]
Возвращают статус 0 или 1 в зависимости от оценки условного выражения выражение.
Выражения состоят из основных элементов, описанных ниже в разделе УСЛОВНЫЕ ВЫРАЖЕНИЯ.
Следовательно, код выхода равен 1:
[[ ! 2 -eq 2 && 3 -eq 4 ]]
Потому что это фактически эквивалентно этому:
[[ ( ! 2 -eq 2 ) && ( 3 -eq 4 ) ]]
При этом, из-за укороченного вычисления, правая часть &&
никогда не вычисляется и фактически эквивалентна этому гораздо более короткому выражению:
[[ ! 2 -eq 2 ]]
Что всегда будет ложным (1).
Короче говоря: внутри [[
! влияетчастивыражения.
Предпочтительный
Использование !
inside [[
встречается гораздо чаще (и переносимо на большее количество оболочек (с помощью [
)), но иногда может сбивать с толку, если явно не контролировать его с помощью разумного использования ()
для ограничения степени отрицания (что может стать проблемой внутри [
конструкций).
Но (в bash, ksh и zsh) результат ! [[
довольно четко определен и его легче понять: выполнить все [[
и отменить результат.
Какой из них следует использовать — вопрос личных предпочтений (и понимания).