Saya bisa melakukan ini, tetapi perlu membuat string dari variabel kemudian dereferencing. Apakah ada cara untuk mempersingkatnya menjadi pernyataan yang lebih sederhana?
#!/bin/bash
FRUITS="BANANA APPLE ORANGE"
BANANA_COLOUR="Yellow"
APPLE_COLOUR="Green or Red"
ORANGE_COLOUR="Blue"
for fruit in $( echo $FRUITS ); do
fruit_colour="${fruit}_COLOUR"
echo $fruit is ${!fruit_colour}
done
Saya telah mencoba banyak hal seperti ${!"${fruit}_COLOUR"}
atau \$${fruit}_COLOUR
dan banyak varian lainnya, tetapi satu-satunya cara yang berhasil adalah dengan menggunakan string.
bash
variable-substitution
Tikar
sumber
sumber
!
sintaks adalah bendera pada substitusi variabel yang pada dasarnya mengatakan “pengganti dua kali”. Itu tidak mengubah persyaratan bahwa apa yang ada di dalamnya${…}
harus berupa nama variabel. Jadi tidak, Anda tidak dapat menghindari menggunakan variabel yang berisi nama, kecuali jika Anda menggunakan metode yang berbeda (eval
).Jawaban:
Off pertama, Anda tidak perlu menggunakan
$(echo $FRUITS)
dalamfor
pernyataan. Menggunakan keadilan saja$FRUITS
sudah cukup. Kemudian Anda bisa menghilangkan salah satu garis di dalam loop, dengan menggunakaneval
.The
eval
hanya memberitahu bash untuk membuat kedua evaluasi dari pernyataan berikut (yaitu satu lebih dari evaluasi normal). Yang\$
bertahan evaluasi pertama sebagai$
, dan evaluasi berikutnya kemudian memperlakukan ini$
sebagai awal nama variabel, yang memutuskan untuk "Kuning", dll.Dengan cara ini Anda tidak perlu memiliki langkah terpisah yang membuat string sementara (yang menurut saya adalah tujuan utama pertanyaan Anda).
Untuk metode alternatif, seperti yang disebutkan oleh Patrick dalam komentar (di atas), Anda bisa menggunakan array asosiatif , di mana indeks elemen tidak perlu bilangan bulat. Anda dapat menggunakan string, seperti nama jenis buah. Berikut ini contohnya, menggunakan array asosiatif bash:
sumber
Anda dapat menggunakan bash-builtin
eval
untuk melakukan itu:Perhatikan tanda dolar yang terbalik. Pada dasarnya, garis "eval" menyebabkan
bash
pengganti$fruit
dan${fruit_color}
, kemudian menggunakaneval
untuk melakukan putaran kedua substitusi sebelum memanggilecho
.sumber
Anda tidak perlu pernyataan eval.
eval
adalah petunjuk dalam sebagian besar bahasa bahwa Anda melakukan sesuatu yang salah.sumber
eval
karena setidaknya orang tahu itu berbahaya,${!var}
sama berbahayanya denganbash
(juga kerentanan perintah injeksi jika$chosen_prefix
berada di bawah kendali penyerang) dan lebih sedikit orang yang menyadarinya. Cobavar_name='a[$(uname>&2)0]' bash -c 'v=${!var_name}'
. Pendekatan terbaik di sini adalah array asosiatif.