Подтвердить что ты не робот

Bash если с или и отрицание

почему:

#!/bin/bash
wtf=false
if [ $wtf ] || [ ! -f filethatexists.whatever ]
then
 echo "WTF1"
fi
if [ ! -f filethatexists.whatever ]
then
 echo "WTF2"
fi

Печать

WTF1

вместо ничего? Особенно удручает, что вторая форма работает так, как ожидалось, и первая не.

4b9b3361

Ответ 1

Основной тест

[ $wtf ]

проверяет, является ли строка посередине пустой или нет.

Так как $wtf содержит строку 'false', тест возвращает true или завершает статус 0 для успеха, потому что 'false' не совпадает с пустой строкой '' - и, следовательно, вы получаете WTF1 как ответ.

Попробуйте:

wtf=''

Как указано Гордон ДэвиссонДеннис Уильямсон), это хорошая идея быть осторожно со строками, которые вы тестируете. В самом деле, я должен был заявить, что всегда буду использовать [ -n "$wtf" ] или [ -z "$wtf" ], чтобы проверить, установлена ​​ли переменная, потому что это было необходимо, когда я изучал оболочку, когда-то четверть века назад. У меня есть счетчики из Bash afficionados, которые вам не нужно беспокоиться об этом в Bash. Однако, я думаю, что здесь код содержит встречный пример, который на самом деле вам все равно придется беспокоиться об этом.

Итак, некоторые лучшие практики:

  • Заменить проверенные переменные в двойных кавычках или
  • (В Bash) используйте [[ $wtf ]], который знает, как обрабатывать расширение переменной.
  • Используйте теги -n или -z для проверки непустых или пустых значений.

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

Рассмотрим код:

wtf="1 -eq 0"
 [  $wtf  ]  && echo "WTF0"
[[  $wtf  ]] && echo "WTF1"
wtf="false"
 [  $wtf  ]  && echo "WTF2"
[[  $wtf  ]] && echo "WTF3"
wtf=""
 [  $wtf  ]  && echo "WTF4"
[[  $wtf  ]] && echo "WTF5"
wtf="false"
 [ "$wtf" ]  && echo "WTF6"
[[ "$wtf" ]] && echo "WTF7"
wtf=""
 [ "$wtf" ]  && echo "WTF8"
[[ "$wtf" ]] && echo "WTF9"

Это производит:

WTF1
WTF2
WTF3
WTF6
WTF7

как с Bash, так и с ksh (как показано на MacOS X 10.6.4, при запуске с 'bash testcode.sh' или 'ksh testcode.sh'). Настоящая оболочка Борна (если вы все еще можете найти такую ​​вещь) будет возражать против операций с двумя скобками - она ​​не сможет найти команду "[[" на $PATH.

Вы можете расширить тестирование, чтобы охватить больше случаев ad nauseam.

Ответ 2

Вот удобный небольшой трюк:

wtf=false
if $wtf || [ ! -f filethatexists.whatever ]

В этой форме содержимое переменной выполняется, а возвращаемое значение определяет, проходит или не проходит тест. Бывает, что true и false являются Bash встроенными, которые возвращают соответствующее значение.

Ответ 3

if [ $wtf = true ] || [ ! -f . .