Qual è il modo più semplice tramite script per verificare se viene esportata una variabile shell?


20

Per alcune sessioni di shell voglio essere in grado di stampare un flag di avviso se una variabile di shell non è impostata ed esportata.

È abbastanza semplice fare una cosa del genere per stampare "Errore" nel prompt se SET_MEnon è impostato o è nullo.

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

Tuttavia, questo non riesce a contrassegnare se ho impostato SET_MEsenza esportarlo, che è un errore che voglio essere in grado di rilevare. A corto di qualcosa di simile $(bash -c 'test -z "$SET_ME" && echo Error;')o grepping dell'output export, c'è un semplice controllo che posso fare per testare se SET_MEè stato esportato?

Una soluzione non POSIX, solo bash è completamente accettabile.

Risposte:


11

Utilizzare il declarecomando e l'operatore di corrispondenza delle espressioni regolari:

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

Penso che sia quello che sto cercando. In teoria, potrebbe essere necessario essere più flessibili, ad esempio se avessi una variabile esportata in sola lettura, ma in pratica non uso mai altri typesetattributi.
CB Bailey,

Buon punto. Lo riparerò per i posteri.
Chepner,

Sembra che il tentativo di citare l'espressione regolare ne impedisca il funzionamento come espressione regolare in bash> = 3.2.
CB Bailey,

Inoltre c'è un'incoerenza, -z "$1"presume che sto passando il valore di una variabile a test_var(come ero) mentre si declare -paspetta il suo nome. Sono venuto con questo test, che prende il nome di una variabile di shell: test_exported_notnull () { re='^declare -\w*x'; [[ -n $(eval echo \$$1) ]] && [[ $(declare -p "$1") =~ $re ]]; }.
CB Bailey,

Per evitare il eval, basta aggiungere questa prima riga:, var=$1quindi utilizzare [[ -z "${!var}" ]] && echo Error.
Chepner,

4

Sono consapevole che la domanda ha 3 anni, tuttavia si potrebbe trovare più semplice la seguente soluzione:

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

risponde, se la variabile viene esportata e ha un valore non vuoto.


4

In Bash 4.4 o versioni successive , è possibile utilizzare l' ${parameter@a} espansione dei parametri della shell per ottenere un elenco di attributi su un parametro, incluso se viene esportato.

Ecco una semplice funzione dimostrativa ${parameter@a}, che ti dirà se una determinata variabile viene esportata, dato il suo nome:

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

Esempio di utilizzo:

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

Come funziona:

Il formato restituito da ${parameter@a}è un carattere per attributo, con il significato di ciascun carattere di attributo proveniente dalle opzioni corrispondenti dal comando declare - in questo caso, vogliamo cercare x- esportato.


Migliore risposta se stai usando Bash 4.4 o più recente!
Andy,

3

È possibile utilizzare compgencon la sua -Xopzione per determinare se una variabile viene esportata:

compgen -e -X "!$MAY_BE_EXPORTED_VARIABLE"

Per esempio:

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

La migliore risposta compatibile! Oltre il doppio della soluzione $ {parameter @ a}, ma molto più compatibile per i casi bash 3.2
Andy,

2

Se mi rassegno a dover usare exporte grep, il test più semplice è probabilmente qualcosa del genere.

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

o se voglio anche un valore nullo:

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

1
POSIX 7 afferma che exportnon è specificato e definisce un formato preciso per export -psimile a bash exportma diverso. Ma bash sembra ignorare POSIX e usare lo stesso formato exportdi export -p!
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

1

Il exportcomando, fornito senza parametri, fornisce un elenco di nomi esportati nell'ambiente corrente:

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

Alcuni tagli e sedimenti si liberano della lanugine:

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

C'è il tuo elenco di esportazioni, pronto per ulteriori elaborazioni.


1
Questo funziona, ma speravo in una risposta più leggera con meno forcelle implicite (quindi "A corto di [...] grepping l'output di export") poiché il mio uso pianificato è nel mio prompt.
CB Bailey,

@CharlesBailey: capisco. Sono arrivato a questo cercando la manpage di bash export, e questa è stata l'unica cosa che mi è venuta in mente. Neanche un aiuto dalla shell riesce a fuggire. Il file exportè comunque incorporato, ma dubito che tu possa evitare il grep.
DevSolar,

1

Il metodo più semplice a cui attualmente riesco a pensare:

[ bash -c ': ${v1?}' 2>/dev/null ]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.