Проверьте, не установлена ​​ли переменная Bash, используя функцию - PullRequest
28 голосов
/ 17 мая 2009

Простой тест переменной Bash:

${varName:?    "${varName} is not defined"}

Я бы хотел использовать это снова, поместив в функцию. Как пожалуйста?

После неудачи

#
# Test a variable exists
tvar(){
 val=${1:?    "${1}    must be defined, preferably in $basedir"}
 if [ -z ${val}  ]
     then 
     echo Zero length value 
 else
     echo ${1} exists, value ${1}
 fi
}

т.е. Мне нужно выйти, если тест не пройден.

Ответы [ 7 ]

46 голосов
/ 24 сентября 2009

Благодаря ответу lhunath меня привели к части страницы Bash man, которую я пропускал сотни раз:

    When  not performing substring  expansion, bash tests for a parameter that
    is unset  or null; omitting the colon results in a test only for a parame‐
    ter that is unset.

Это побудило меня создать следующую таблицу истинности:


                | unset |   set    | set and  | meaning
                |       | but null | not null |
    ============+=======+==========+==========+=============================
     ${var-_}   |   T   |     F    |    T     | not null or not set
    ------------+-------+----------+----------+-----------------------------
     ${var:-_}  |   T   |     T    |    T     | always true, use for subst.
    ------------+-------+----------+----------+-----------------------------
     $var       |   F   |     F    |    T     | var is set and not null
    ------------+-------+----------+----------+-----------------------------
     ${!var[@]} |   F   |     T    |    T     | var is set

Эта таблица представляет спецификацию в последнем ряду. На странице Bash man написано: «Если имя не является массивом, расширяется до 0, если имя установлено, и ноль в противном случае». Для целей этой таблицы истинности она ведет себя одинаково, даже если это массив.

19 голосов
/ 17 мая 2009

То, что вы ищете, это косвенное.

assertNotEmpty() {
    : "${!1:? "$1 is empty, aborting."}"
}

Это приводит к прерыванию работы сценария с сообщением об ошибке, если вы делаете что-то вроде этого:

$ foo=""
$ assertNotEmpty foo
bash: !1:  foo is empty, aborting.

Если вы просто хотите проверить , является ли foo пустым, вместо прерывания сценария, используйте это вместо функции:

[[ $foo ]]

Например:

until read -p "What is your name? " name && [[ $name ]]; do
    echo "You didn't enter your name.  Please, try again." >&2
done

Также обратите внимание, что существует очень важное различие между пустым и unset параметром. Вы должны позаботиться о том, чтобы не перепутать эти условия! Пустой параметр - это тот, который установлен, но просто установлен в пустую строку. Неустановленный параметр - это тот, который вообще не существует.

Все предыдущие примеры тестируют параметры empty . Если вы хотите проверить неустановленные параметры и считать все установленные параметры в порядке, независимо от того, пусты они или нет, используйте это:

[[ ! $foo && ${foo-_} ]]

Используйте его в такой функции:

assertIsSet() {
    [[ ! ${!1} && ${!1-_} ]] && {
        echo "$1 is not set, aborting." >&2
        exit 1
    }
}

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

$ ( foo="blah"; assertIsSet foo; echo "Still running." )
Still running.
$ ( foo=""; assertIsSet foo; echo "Still running." )
Still running.
$ ( unset foo; assertIsSet foo; echo "Still running." )
foo is not set, aborting.
5 голосов
/ 26 ноября 2012

Вы хотите использовать [ -z ${parameter+word} ]

Некоторая часть man bash:

Parameter Expansion
    ...
    In  each  of  the cases below, word is subject to tilde expansion, parameter expansion, command substitution, and
    arithmetic expansion.  When not performing substring expansion, bash tests for a parameter that is unset or null;
    omitting the colon results in a test only for a parameter that is unset.
    ...
    ${parameter:+word}
           Use Alternate Value.  If parameter is null or unset, nothing is substituted, otherwise  the  expansion  of
           word is substituted.
    ...

другими словами:

    ${parameter+word}
           Use Alternate Value.  If parameter is unset, nothing is substituted, otherwise  the  expansion  of
           word is substituted.

некоторые примеры:

$ set | grep FOOBAR
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
it is unset
$ declare FOOBAR
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
$ FOOBAR=
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
$ FOOBAR=1
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
$ unset FOOBAR
$ if [ -z "${FOOBAR+something}" ]; then echo "it is unset"; fi
it is unset
$
3 голосов
/ 15 мая 2011

Эта функция проверяет переменные, которые ТОЛЬКО установлены. Переменная может даже быть массивом. Обратите внимание, что в bash: 0 == TRUE, 1 == FALSE.

function var.defined {
    eval '[[ ${!'$1'[@]} ]]'
}

# Typical Usage of var.defined {}

declare you="Your Name Here" ref='you';

read -p "What's your name: " you;

if var.defined you; then   # Simple demo using literal text

    echo "BASH recognizes $you";
    echo "BASH also knows a reference to $ref as ${!ref}, by indirection."; 

fi

unset you # have just been killed by a master :D

if ! var.defined $ref; then    # Standard demo using an expanded literal value

    echo "BASH doesn't know $ref any longer";

fi

read -s -N 1 -p "Press any key to continue...";
echo "";

Итак, чтобы быть понятным, функция проверяет буквальный текст. Каждый раз, когда команда вызывается в bash, переменные, как правило, «заменяются» или «заменяются» базовым значением, если только:

  • $ varRef ($) экранируется: \ $ varRef
  • $ varRef - одиночная кавычка '$ varRef'
1 голос
/ 06 ноября 2010

Не уверен, что это именно то, что вам нужно, но удобный трюк, который я использую при написании нового + сложного скрипта, заключается в использовании "set -o"

set -o # заставит скрипт взорваться, когда найдет неустановленную переменную

EG:

$ grep '$ 1' chex.sh

кейс "$ 1" в

$ ./chex.sh

. / Chex.sh: строка 111: $ 1: несвязанная переменная

$ ./chex.sh foo

неверно / опции не переданы .. выход

1 голос
/ 17 мая 2009

Я не совсем понял, что вам нужно. Я пытаюсь ответить тебе, несмотря на это.

т.е. Мне нужно выйти, если тест не пройден.

Код:

${varName:?    "${varName} is not defined"}

вернет ненулевой код завершения, когда нет переменной с именем "varName". Код выхода последней команды сохраняется в $?.

О вашем коде:

val=${1:?    "${1}    must be defined, preferably in $basedir"}

Может быть, он не делает то, что вам нужно. В случае, если $1 не определен, "${1}" будет заменен ничем. Возможно, вы хотите использовать одинарные кавычки, которые буквально пишут ${1} без подстановки.

val=${1:?    '${1}    must be defined, preferably in $basedir'
0 голосов
/ 01 июня 2014
if set | grep -q '^VARIABLE='
then 
    echo VARIABLE is set
fi
...