Untuk versi Bash sebelum "GNU bash, Versi 4.2" apakah ada alternatif yang setara untuk -v
opsi test
perintah? Sebagai contoh:
shopt -os nounset
test -v foobar && echo foo || echo bar
# Output: bar
foobar=
test -v foobar && echo foo || echo bar
# Output: foo
-v
bukan pilihan untuktest
, tetapi operator untuk ekspresi kondisional.option
to a commandtest -v
, anoperator
to aconditional expression
dan aunary test primary
for[ ]
. Jangan mencampur bahasa Inggris dengan definisi shell.Jawaban:
Portabel untuk semua kulit POSIX:
Buat itu
${foobar:+1}
jika Anda ingin memperlakukanfoobar
dengan cara yang sama apakah itu kosong atau tidak ditentukan. Anda juga dapat menggunakan${foobar-}
untuk mendapatkan string kosong saatfoobar
tidak terdefinisi dan nilaifoobar
sebaliknya (atau masukkan nilai default lainnya setelah-
).Dalam ksh, jika
foobar
dideklarasikan tetapi tidak didefinisikan, seperti dalamtypeset -a foobar
, kemudian${foobar+1}
memperluas ke string kosong.Zsh tidak memiliki variabel yang dideklarasikan tetapi tidak disetel:
typeset -a foobar
membuat array kosong.Dalam bash, array berperilaku dengan cara yang berbeda dan mengejutkan.
${a+1}
hanya mengembang ke1
jikaa
array tidak kosong, misPrinsip yang sama berlaku untuk array asosiatif: variabel array diperlakukan sebagaimana didefinisikan jika mereka memiliki kumpulan indeks yang tidak kosong.
Cara berbeda, spesifik bash untuk menguji apakah variabel jenis apa pun telah ditetapkan adalah untuk memeriksa apakah variabel tersebut terdaftar . Laporan ini mengosongkan array seperti yang didefinisikan, tidak seperti , tetapi melaporkan variabel yang dideklarasikan tetapi tidak ditugaskan ( ) sebagai tidak terdefinisi.
${!PREFIX*}
${foobar+1}
unset foobar; typeset -a foobar
Ini sama dengan menguji nilai pengembalian
typeset -p foobar
ataudeclare -p foobar
, kecuali yangtypeset -p foobar
gagal pada variabel yang dideklarasikan tetapi tidak ditetapkan.Di bash, seperti di ksh,
set -o nounset; typeset -a foobar; echo $foobar
memicu kesalahan dalam upaya memperluas variabel yang tidak ditentukanfoobar
. Tidak seperti di ksh,set -o nounset; foobar=(); echo $foobar
(atauecho "${foobar[@]}"
) juga memicu kesalahan.Perhatikan bahwa dalam semua situasi yang dijelaskan di sini,
${foobar+1}
perluas string kosong jika dan hanya jika$foobar
akan menyebabkan kesalahanset -o nounset
.sumber
echo "${foobar:+1}"
tidak mencetak1
jikadeclare -a foobar
sebelumnya dikeluarkan dan dengan demikianfoobar
merupakan array yang diindeks.declare -p foobar
melaporkan dengan benardeclare -a foobar='()'
. Apakah"${foobar:+1}"
hanya berfungsi untuk variabel non-array?${foobar+1}
(tanpa:
, saya membalikkan dua contoh dalam jawaban asli saya) benar untuk array dalam bash jika definisi Anda tentang "didefinisikan" adalah "akan$foobar
bekerja di bawahset -o nounset
". Jika definisi Anda berbeda, bash agak aneh. Lihat jawaban saya yang diperbarui.0
indeks atau kunci yang didefinisikan sebagaimana adanyaa=()
,${a+1}
benar tidak menghasilkan apa-apa.defined
operator.Test
bisa melakukan itu; itu tidak sulit ( um ....)Singkatnya dengan jawaban Gilles saya membuat aturan berikut:
[[ -v foobar ]]
untuk variabel dalam versi Bash> = 4.2.declare -p foobar &>/dev/null
untuk variabel array dalam versi Bash <4.2.(( ${foo[0]+1} ))
atau(( ${bar[foo]+1} ))
untuk langganan masing-masing array yang diindeks (-a
) dan diketik (-A
) (declare
). Opsi 1 dan 2 tidak berfungsi di sini.sumber
Saya menggunakan teknik yang sama untuk semua variabel di bash, dan itu berfungsi, misalnya:
output:
sementara
output:
sumber
foobar=""
kemudian akan melaporkan itufoobar is unset
. Tidak tunggu, saya ambil kembali. Benar-benar hanya menguji apakah elemen pertama kosong atau tidak, jadi sepertinya hanya ide yang bagus jika Anda tahu variabel BUKAN array, dan Anda hanya peduli kekosongan, bukan ketajaman.