18

Для некоторых сеансов оболочки я хочу иметь возможность печатать флаг предупреждения, если переменная оболочки не установлена и не экспортирована.

Довольно просто сделать что-то подобное, чтобы напечатать "Error" в приглашении, если SET_ME не установлен или имеет значение null.

test_var () { test -z "$1" && echo Error; }
PS1='$(test_var "$SET_ME") \$ '

Однако это не помечается, если я установил SET_ME без его экспорта, что является ошибкой, которую я хочу обнаружить. Если не считать что-то вроде $(bash -c 'test -z "$SET_ME" && echo Error;') или получения результата export , есть ли простая проверка, которую я могу сделать, чтобы проверить, экспортирован ли SET_ME ?

Не POSIX, bash-only решение полностью приемлемо.

7 ответов7

10

Используйте команду declare и оператор сопоставления регулярного выражения:

test_var () {
    # $1 - name of a shell variable
    var=$1
    [[ -z "${!var}" ]] && echo Error
    [[ $(declare -p $1)  =~ ^declare\ -[aAilrtu]*x[aAilrtu]*\  ]] || echo Error
}
4

Я знаю, что этому вопросу уже 3 года, но можно найти следующее решение проще:

[ "$(bash -c 'echo ${variable}')" ]

ответы, если переменная экспортирована и имеет непустое значение.

2

Вы можете использовать compgen с опцией -X чтобы определить, экспортируется ли переменная:

compgen -e -X "!$MAY_BE_EXPORTED_VARIABLE"

Например:

$ NOT_EXPORTED="xxx"
$ compgen -e -X '!SHELL'
SHELL
$ compgen -e -X '!NOT_EXPORTED'
$ echo $?
1
2

Если я смирюсь с необходимостью использовать export и grep , то, наверное, самый простой тест будет примерно таким.

export | grep -Eq '^declare -x SET_ME='

или если я хочу также ненулевое значение:

export | grep -Eq '^declare -x SET_ME=".+"'
2

В Bash 4.4 или более поздней версии вы можете использовать расширение параметра оболочки ${parameter@a} чтобы получить список атрибутов о параметре, в том числе, если он экспортирован.

Вот простая функция, демонстрирующая ${parameter@a} , которая сообщит вам, экспортируется ли данная переменная, учитывая ее имя:

function is_exported {
    local name="$1"
    if [[ "${!name@a}" == *x* ]]; then
        echo "Yes - '$name' is exported."
    else
        echo "No - '$name' is not exported."
    fi
}

Пример использования:

$ is_exported PATH
Yes - 'PATH' is exported.
$ foo=1 is_exported foo
Yes - 'abc' is exported.
$ bar=1; is_exported bar
No - 'abc' is not exported.
$ export baz=1; is_exported baz
Yes - 'baz' is exported.
$ export -n baz; is_exported baz
No - 'baz' is not exported.
$ declare -x qux=3; is_exported qux
Yes - 'qux' is exported.

Как это устроено:

Формат, возвращаемый ${parameter@a} равен одному символу на атрибут, причем значение каждого символа атрибута определяется соответствующими параметрами команды объявлений - в этом случае мы хотим искать экспортированный x .

1

Команда export , заданная без параметров, выдает список экспортированных имен в текущей среде:

$ FOO1=test
$ FOO2=test
$ export | grep FOO
$ export FOO2
$ export | grep FOO
declare -x FOO2="test"

Некоторая стрижка и сединг избавляет от пуха:

export | cut -d' ' -f 3- | sed s/=.*//

Вот ваш список экспорта, готовый для дальнейшей обработки.

1

Самый простой метод, который я сейчас могу представить:

[ bash -c ': ${v1?}' 2>/dev/null ]

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .