Apa cara skrip yang paling sederhana untuk memeriksa apakah variabel shell diekspor?

20

Untuk beberapa sesi shell saya ingin dapat mencetak bendera peringatan jika variabel shell tidak diatur dan diekspor.

Cukup mudah untuk melakukan hal seperti ini untuk mencetak "Kesalahan" pada prompt jika SET_MEtidak disetel atau null.

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

Namun ini gagal menandai jika saya mengatur SET_MEtanpa mengekspornya, yang merupakan kesalahan yang ingin saya deteksi. Kurang dari sesuatu seperti $(bash -c 'test -z "$SET_ME" && echo Error;')atau menangkap output export, apakah ada pemeriksaan sederhana yang dapat saya lakukan untuk menguji apakah SET_MEtelah diekspor?

Solusi non-POSIX, bash-only sepenuhnya dapat diterima.

CB Bailey
sumber

Jawaban:

11

Gunakan declareperintah dan operator pencocokan ekspresi reguler:

test_var () {
    # $1 - name of a shell variable
    var=$1
    [[ -z "${!var}" ]] && echo Error
    [[ $(declare -p $1)  =~ ^declare\ -[aAilrtu]*x[aAilrtu]*\  ]] || echo Error
}
chepner
sumber
Saya pikir inilah yang saya cari. Secara teori, ulang mungkin perlu lebih fleksibel, misalnya jika saya memiliki variabel yang diekspor hanya baca, tetapi dalam praktiknya saya tidak pernah menggunakan typesetatribut lain .
CB Bailey
Poin bagus. Saya akan memperbaikinya untuk anak cucu.
chepner
Sepertinya berusaha mengutip ekspresi reguler berhenti berfungsi sebagai ekspresi reguler di bash> = 3.2.
CB Bailey
Juga ada ketidakkonsistenan, -z "$1"menganggap saya melewati nilai variabel ke test_var(seperti saya) sedangkan declare -pmengharapkan namanya. Saya datang dengan tes ini yang mengambil nama dari variabel shell: test_exported_notnull () { re='^declare -\w*x'; [[ -n $(eval echo \$$1) ]] && [[ $(declare -p "$1") =~ $re ]]; }.
CB Bailey
Untuk menghindarinya eval, tambahkan saja baris pertama ini:, var=$1lalu gunakan [[ -z "${!var}" ]] && echo Error.
chepner
4

Saya sadar pertanyaannya adalah 3 tahun, namun orang dapat menemukan solusi berikut lebih sederhana:

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

jawaban, jika variabel diekspor dan memiliki nilai tidak kosong.

ArturFH
sumber
4

Di Bash 4.4 atau lebih baru , Anda bisa menggunakan ${parameter@a} ekspansi parameter shell untuk mendapatkan daftar atribut tentang parameter, termasuk jika diekspor.

Ini adalah fungsi sederhana yang diperagakan ${parameter@a}, yang akan memberi tahu Anda jika variabel yang diberikan diekspor, diberi namanya:

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

Contoh penggunaan:

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

Bagaimana itu bekerja:

Format yang dikembalikan oleh ${parameter@a}adalah satu karakter per atribut, dengan arti setiap karakter atribut berasal dari opsi yang sesuai dari perintah mendeklarasikan - dalam hal ini, kami ingin mencari x- diekspor.

Robert Hencke
sumber
Jawaban Terbaik jika Anda menggunakan Bash 4.4 atau yang lebih baru!
Andy
3

Anda dapat menggunakan compgendengan yang -Xpilihan untuk menentukan apakah variabel diekspor:

compgen -e -X "!$MAY_BE_EXPORTED_VARIABLE"

Misalnya:

$ NOT_EXPORTED="xxx"
$ compgen -e -X '!SHELL'
SHELL
$ compgen -e -X '!NOT_EXPORTED'
$ echo $?
1
Eric Pruitt
sumber
Jawaban kompatibel terbaik! Lebih dari dua kali lebih lambat dari solusi $ {parameter @ a}, tetapi jauh lebih kompatibel untuk kasus bash 3.2
Andy
2

Jika saya pasrah harus menggunakan exportdan grep, tes paling sederhana mungkin adalah sesuatu seperti ini.

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

atau jika saya ingin non-null juga:

export | grep -Eq '^declare -x SET_ME=".+"'
CB Bailey
sumber
1
POSIX 7 mengatakan bahwa exportitu tidak ditentukan, dan mendefinisikan format yang tepat untuk export -pmirip dengan bash exporttetapi berbeda. Tetapi bash tampaknya mengabaikan POSIX dan menggunakan format yang sama seperti exportuntuk export -p!
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件
1

The exportperintah, diberikan tanpa parameter, memberikan daftar nama diekspor dalam lingkungan saat ini:

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

Beberapa pemotongan dan seding menghilangkan bulu:

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

Ada daftar ekspor Anda, siap untuk diproses lebih lanjut.

DevSolar
sumber
1
Ini berfungsi tetapi saya berharap untuk jawaban yang lebih ringan dengan garpu tersirat lebih sedikit (maka "Pendek [...] menangkap output export") karena penggunaan yang direncanakan ada pada prompt saya.
CB Bailey
@CharlesBailey: Begitu. Saya datang ke sini dengan mencari bash manpage export, dan ini adalah satu-satunya hal yang saya dapatkan. Tidak ada bantuan dari shell yang lolos. Itu exportsudah builtin, tapi saya ragu Anda bisa menghindari grep.
DevSolar
1

Metode paling sederhana yang saya pikirkan saat ini:

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