Dengan fungsi pembantu:
#!/bin/bash
to_param_list () {
declare -n outlist=$1
declare -n inhash=$2
for param in "${!inhash[@]}"; do
outlist+=( "--$param=${inhash[$param]}" )
done
}
declare -A my_vars=( ["key1"]="value1" ["key2"]="value" )
to_param_list list my_vars
my_script.sh "${list[@]}"
Perintah terakhir dalam skrip di atas akan diperluas menjadi setara dengan yang telah ditulis
my_script.sh "--key2=value" "--key1=value1"
The to_param_list
Fungsi mengambil nama dari variabel array dan nama dari variabel array asosiatif dan menggunakan ini untuk membuat dua "referensi nama" variabel dalam fungsi (namerefs diperkenalkan pada bash
rilis 4.3). Ini kemudian digunakan untuk mengisi variabel array yang diberikan dengan kunci dan nilai dalam format yang sesuai dari array asosiatif.
Pengulangan dalam fungsi berulang "${!inhash[@]}"
, yang merupakan daftar kunci yang dikutip secara individual dalam array asosiatif Anda.
Setelah pemanggilan fungsi kembali, skrip akan menggunakan array untuk memanggil skrip atau perintah Anda yang lain.
Menjalankan di atas dengan
declare -A my_vars=( ["key1"]="hello world" ["key2"]="some thing" ["key3"]="* * *" )
to_param_list list my_vars
printf 'Arg: %s\n' "${list[@]}"
script akan ditampilkan
Arg: --key2=some thing
Arg: --key3=* * *
Arg: --key1=hello world
Ini menunjukkan bahwa opsi dihasilkan tanpa pemisahan kata atau penggumpalan nama file mulai berlaku. Ini juga menunjukkan bahwa urutan kunci tidak dapat dipertahankan karena mengakses kunci dari array asosiatif akan melakukannya dalam urutan yang cukup acak.
Anda tidak dapat benar-benar menggunakan substitusi perintah dengan aman di sini karena itu akan menjadi string tunggal. Jika tidak dikutip, string ini kemudian akan dipisah pada karakter spasi putih (secara default), yang juga akan membagi kunci dan nilai array asosiatif Anda. Shell juga akan melakukan nama file globbing pada kata-kata yang dihasilkan. Mengutip dua kali substitusi perintah tidak akan membantu karena itu akan menghasilkan panggilan Anda my_script.sh
dengan satu argumen.
Mengenai masalah Anda denganmakeself
:
The makeself
Script melakukan ini dengan argumen untuk installer script Anda:
SCRIPTARGS="$*"
Ini menyimpan argumen sebagai string dalam $SCRIPTARGS
(disatukan, dipisahkan oleh spasi). Ini kemudian dimasukkan ke dalam arsip self-extracting apa adanya. Agar opsi diuraikan dengan benar ketika mereka dievaluasi kembali (yang mana ketika menjalankan installer), Anda harus memberikan seperangkat tanda kutip tambahan dalam nilai-nilai parameter agar mereka dibatasi secara tepat.
installer_param_array=( ["upgrade-from"]="'19 .2.0'" ["upgrade-to"]="'19.3.0'" )
Perhatikan bahwa ini bukan bug dalam kode saya. Ini hanya efek samping dari makeself
pembuatan kode shell berdasarkan nilai yang diberikan pengguna.
Idealnya, makeself
skrip seharusnya menulis masing-masing argumen yang disediakan dengan seperangkat tanda kutip tambahan di sekitar mereka, tetapi tidak, mungkin karena sulit untuk mengetahui efek apa yang mungkin terjadi. Sebagai gantinya, ia menyerahkannya kepada pengguna untuk memberikan penawaran tambahan ini.
Menjalankan kembali pengujian saya dari atas, tetapi sekarang dengan
declare -A my_vars=( ["key1"]="'hello world'" ["key2"]="'some value'" ["key3"]="'* * *'" )
to_param_list list my_vars
printf 'Arg: %s\n' "${list[@]}"
menghasilkan
Arg: --key2='some value'
Arg: --key3='* * *'
Arg: --key1='hello world'
Anda dapat melihat bahwa string ini , ketika dievaluasi kembali oleh shell, tidak akan terpecah pada spasi.
Jelas, Anda bisa menggunakan array asosiatif awal Anda dan sebagai gantinya menambahkan kutipan dalam to_param_list
fungsi dengan mengubah
outlist+=( "--$param=${inhash[$param]}" )
ke
outlist+=( "--$param='${inhash[$param]}'" )
Salah satu dari perubahan ini pada kode Anda akan menyertakan tanda kutip tunggal dalam nilai-nilai opsi, sehingga evaluasi ulang dari nilai-nilai akan menjadi perlu .
my_script.sh "$(declare -p thearray)$"
. Dimyscript.sh
Anda membacanya dengansource /dev/stdin <<<"$1"
Lalu Anda milikithearray
di skrip Anda. Anda dapat memiliki argumen lain di samping array. Anda dapat melewati banyak variabel:my_script.sh "$(declare -p var1 var2 ...)"
dalam argumen tunggal ini.