Який найпростіший сценарій перевірити, чи експортується змінна оболонки?


20

Для деяких сеансів оболонки я хочу мати можливість надрукувати попереджувальний прапор, якщо змінна оболонки не встановлена ​​та експортована.

Зробити щось подібне досить просто, щоб надрукувати "Помилка" у запиті, якщо SET_MEвона не встановлена ​​чи недійсна.

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, тільки для удару, є цілком прийнятним.

Відповіді:


11

Використовуйте declareкоманду та оператор відповідності регулярних виразів:

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

Я думаю, що це те, що я шукаю. Теоретично, повтор може бути більш гнучким, наприклад, якщо б у мене була експортована змінна лише для читання, але на практиці я ніколи не використовую інших typesetатрибутів.
CB Bailey

Гарна думка. Я виправлю це для нащадків.
чепнер

Схоже, спроба цитувати регулярний вираз припиняє його працювати як регулярний вираз у bash> = 3.2.
CB Bailey

Також є невідповідність, -z "$1"припускаючи, що я передаю значення змінної test_var(як я був), тоді як declare -pочікує її імені. Я прийшов з цим тестом , який приймає ім'я змінної оболонки: test_exported_notnull () { re='^declare -\w*x'; [[ -n $(eval echo \$$1) ]] && [[ $(declare -p "$1") =~ $re ]]; }.
CB Bailey

Щоб уникнути цього eval, просто додайте цей перший рядок:, var=$1а потім використовуйте [[ -z "${!var}" ]] && echo Error.
чепнер

4

Мені відомо, що 3 роки це питання, однак таке рішення може бути більш простим:

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

відповідає, якщо змінна експортується і має не порожнє значення.


4

У 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- експортується.


Найкращий відповідь, якщо ви використовуєте Bash 4.4 або новішу!
Енді

3

Ви можете використовувати compgenйого -Xпараметр для визначення експорту змінної:

compgen -e -X "!$MAY_BE_EXPORTED_VARIABLE"

Наприклад:

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

Найкраща сумісна відповідь! Більше вдвічі повільніше, ніж рішення $ {parameter @ a}, але набагато сумісніше для башти 3.2 випадків
Енді,

2

Якщо я відмовлюся від необхідності користуватися exportі grep, мабуть, найпростіший тест - це щось подібне.

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

або якщо я теж хочу нестандартно:

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

1
POSIX 7 говорить, що exportце не визначено, і визначає точний формат, export -pподібний до bash, exportале інший. Але, схоже, bash ігнорує POSIX і використовує той же формат, що і exportдля export -p!
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

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
Це спрацьовує, але я сподівався на більш легку відповідь з меншою кількістю неявних вил (отже, "Недолік [...] схоплення результату export"), оскільки моє заплановане використання є в моєму підказці.
CB Bailey

@CharlesBailey: Я бачу. Я прийшов до цього, шукаючи баш-manpage export, і це було єдине, що я придумав. Не врятується і допомога від оболонки. exportЦе в будь-якому випадку вбудована, але я сумніваюся , що ви можете уникнути grep.
DevSolar

1

Найпростіший метод, про який я зараз можу придумати:

[ bash -c ': ${v1?}' 2>/dev/null ]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.