2013-12-06 2 views
1

Я создаю небольшую библиотеку функций bash, чтобы инкапсулировать некоторые из более загадочных структур синтаксиса bash в подпрограммы, которые я могу быстро использовать и ссылаться. Но для некоторых из них я запускаю неожиданные коды возврата из своих функций. Ниже приведен пример функции «is_undefined». Может ли кто-нибудь объяснить результаты, которые я получаю? (Также представлены ниже.)Почему моя функция bash возвращает неожиданный код возврата?

#!/bin/bash 

is_undefined() 
{ 
    # aka "unset" (not to be confused with "set to nothing") 
    # http://stackoverflow.com/questions/874389/bash-test-for-a-variable-unset-using-a-function 
    [ -z ${1+x} ] 
} 

if [ -z ${UNDEFINED+x} ]; then 
    echo "inline method reports that \$UNDEFINED is undefined" 
fi 

if is_undefined UNDEFINED; then 
    echo "is_undefined() reports that \$UNDEFINED is undefined" 
else 
    echo "is_undefined() reports that \$UNDEFINED is defined" 
fi 

DEFINED= 
if is_undefined DEFINED; then 
    echo "is_undefined() reports that \$DEFINED is undefined" 
else 
    echo "is_undefined() reports that \$DEFINED is defined" 
fi 

Неожиданные результаты:

$ ./test.sh 
inline method reports that $UNDEFINED is undefined 
is_undefined() reports that $UNDEFINED is defined 
is_undefined() reports that $DEFINED is defined 
+1

Добавить 'set -vx', чтобы увидеть, как/что обрабатывается, когда. Удачи. – shellter

+0

В последней версии 'bash' есть оператор' -v', чтобы проверить, установлена ​​ли переменная. '[[-v foo]]' преуспевает, только если 'foo' не установлен; если 'foo' установлен в пустую строку, он терпит неудачу. – chepner

+0

Относительно -v: Мне удалось получить это в моем коде несколько месяцев назад, но забыл документировать ссылку. Я удалил его прошлой ночью, потому что я не нашел его упомянутым в моей книге bash, и googling это не дало никаких результатов. Я думал, что, должно быть, это представлял ... Полагаю, нет! :) –

ответ

3

внутри is_undefined вы тестируете $1, не ${UNDEFINED}, делать, что вам нужно бросить в переменной косвенностью как

is_undefined() { 
    [ -z "${!1+x}" ] 
} 

Тем не менее, это багизм, а не совместимый с posix. Для соответствия posix вам понадобится

is_undefined() { 
    eval "[ -z \${$1+x} ]" 
} 
3

is_undefined UDEFINED возвращает истину, потому что тест внутри is_undefined не испытывает UNDEFINED но $1 и $1является определена. Это значение UNDEFINED.

Итак, ваша функция всегда должна возвращать true, если вы предоставляете параметр. Единственный раз, когда он будет возвращаться ложным, должно быть, когда вы вызываете его без аргументов

is_undefined 

Чтобы получить is_undefined тест фактической переменной, вы можете использовать переменную косвенность с восклицательным знаком ! см Shell Parameter Expansion

is_undefined() 
{ 
    # aka "unset" (not to be confused with "set to nothing") 
    # http://stackoverflow.com/questions/874389/bash-test-for-a-variable-unset-using-a-function 
    [ -z "${!1+x}" ] 
} 
+0

Это имеет смысл. Я делаю, чтобы разыменовать $ 1 внутри этого выражения внутри 'is_undefined()', чтобы получить поведение, которое я хочу? –

+0

Вы можете использовать переменную косвенность, см. Обновленный ответ. –

+0

Спасибо! (Meta: Я не уверен, принимать ли ваш ответ, или @ Ответ yaccz: он немного изменил компонент переменной, но оба ваши ответа были одинаково полезны. Что такое этикет в этом сценарии?) –

Смежные вопросы