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

Bash. Тест для переменной unset, используя функцию

Простой тест переменной 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
}

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

4b9b3361

Ответ 1

Благодаря ответу lhunath's я попал на страницу 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, если имя задано и в противном случае -" null ". Для целей этой таблицы истинности она ведет себя одинаково, даже если это массив.

Ответ 2

То, что вы ищете, является косвенным.

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

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

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

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

[[ $foo ]]

Например:

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

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

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

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

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

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

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

$ ( 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.

Ответ 3

Вы хотите использовать [ -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
$

Ответ 4

Эта функция проверяет переменные, которые ARE CURRENTLY установлены. Переменная может быть даже массивом. Обратите внимание, что в 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 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, переменные GENERALLY "сбрасываются" или "заменяются" базовым значением, если только:

  • $varRef ($):\$varRef
  • $varRef - одинарная кавычка '$ varRef'

Ответ 5

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

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

Код:

${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'

Ответ 6

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

set -o # будет делать бомбу script, когда находит неустановленную переменную

EG:

$grep '$ 1' chex.sh

случай "$ 1" в

$./chex.sh

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

$./chex.sh foo

неверно/без параметров прошло. Выход из

Ответ 7

if set | grep -q '^VARIABLE='
then 
    echo VARIABLE is set
fi