Тестирование, если переменная пуста в сценарии оболочки

27

Я видел следующую технику, которую много раз использовали на разных оболочках, чтобы проверить, является ли переменная пустой:

if [ "x$1" = "x" ]; then 
    # Variable is empty
fi

Есть ли какие-либо преимущества в использовании этого по сравнению с более каноническим if [ -z "$1" ]? Может ли это быть проблема переносимости?

rahmu
источник

Ответы:

17

В некоторых исторических оболочках реализован очень простой синтаксический анализатор, который может быть сбит с толку такими вещами, как, например, [ -n = "" ]где первый операнд =выглядит как оператор, и может анализировать это как [ -n = ]или вызывать синтаксическую ошибку. В [ "x$1" = x"" ], на xпрефикс гарантирует , что x"$1"не может выглядеть как оператор, и поэтому единственным способом оболочка может разобрать этот тест является обработкой в =качестве бинарного оператора.

Все современные оболочки и даже самые старые оболочки, все еще работающие, следуют правилам POSIX, которые обязывают правильно анализировать все тестовые выражения до 4 слов. Так [ -z "$1" ]что это правильный способ проверки, если $1пусто , и [ "$x" = "$y" ]это правильный способ проверить равенство двух переменных.

Даже некоторые текущие оболочки могут быть перепутаны с более длинными выражениями, а некоторые выражения на самом деле неоднозначны, поэтому избегайте использования операторов -aand -oдля создания более длинных логических тестов и вместо этого используйте отдельные вызовы для [собственных &&и ||логических операторов оболочки .

Жиль "ТАК - перестань быть злым"
источник
3
Это не только исторические раковины. Некоторые ksh88, основанные shна некоторых коммерческих Unices, все еще имеют проблему. Смотрите здесь для деталей.
Стефан Шазелас
Это утверждение неверно: [ -z "$1" ]это правильный способ проверки, если $1он пуст . sh -c '[ -z "$1" ]' ''; sh -c '[ -z "$1" ]'- оба возвращают 0, но во втором случае $1не могут быть пустыми, потому что его не существует.
mikeserv
3

Вышеуказанные тесты также вызовут ошибку, если вы запустите "set -u" или "set -o nounset"

Более стабильный способ проверить наличие пустой переменной - использовать расширение параметра :

MYVAR = $ {MYVAR: - "Неверное значение"}

Этот метод работает для традиционной оболочки Bourne, а также для ksh и bash.

Скотт Хоффман
источник
2
Я считаю, что это написано как -> M = $ {M: - "Bad Value"}
Gyan
0
    function isBlank {
 valueNoSpaces=$(echo "$@" | tr -d ' ')

 if [  "$valueNoSpaces" == null ] || [ -z "$valueNoSpaces" ] 
 then
       echo true ;
 else
       echo ""  ;
 fi
}

#Test
if [ $(isBlank "      ") ] 
then
    echo "isBlank \"      \" : it's blank"
else
    echo " isBlank \"      \": it is not blank"
fi

if [ $(isBlank "abc") ] 

then
    echo "isBlank \"abc\" : it's blank"
else
    echo "isBlank \"abc\" :it is not blank"
fi

if [ $(isBlank null) ] 
then
      echo "isBlank null : it's blank"
else
    echo "isBlank null : it is not blank"
fi

if [ $(isBlank "") ] 
then
    echo "isBlank \"\" : it's blank"
else
    echo "isBlank \"\" : it is not blank"
fi

#Result
isBlank "      " : it's blank

isBlank "abc" :it is not blank

isBlank null : it's blank

isBlank "" : it's blank
Аслам Мухаммед
источник
3
Здравствуй! Я не уверен, как это отвечает на вопрос, который спрашивает, почему использовать =против -z, теперь как.
дхаг