Cara yang baik untuk bekerja eval
adalah menggantinya dengan echo
untuk pengujian. echo
dan eval
bekerja sama (jika kita menyisihkan \x
ekspansi yang dilakukan oleh beberapa echo
implementasi seperti bash
dalam beberapa kondisi).
Kedua perintah bergabung dengan argumen mereka dengan satu spasi di antaranya. Perbedaannya adalah bahwa echo
menampilkan hasil saat eval
mengevaluasi / menginterpretasikan sebagai kode shell hasil.
Jadi, untuk melihat kode shell apa
eval $(echo $var_name=$var_value)
akan mengevaluasi, Anda dapat menjalankan:
$ echo $(echo $var_name=$var_value)
fruit=blue orange
Bukan itu yang Anda inginkan, yang Anda inginkan adalah:
fruit=$var_value
Juga, menggunakan di $(echo ...)
sini tidak masuk akal.
Untuk menampilkan yang di atas, Anda akan menjalankan:
$ echo "$var_name=\$var_value"
fruit=$var_value
Jadi, untuk menafsirkannya, itu hanya:
eval "$var_name=\$var_value"
Perhatikan bahwa ini juga dapat digunakan untuk mengatur elemen array individual:
var_name='myarray[23]'
var_value='something'
eval "$var_name=\$var_value"
Seperti yang orang lain katakan, jika Anda tidak peduli kode Anda bash
spesifik, Anda dapat menggunakan declare
sebagai:
declare "$var_name=$var_value"
Namun perhatikan bahwa ia memiliki beberapa efek samping.
Ini membatasi ruang lingkup variabel ke fungsi di mana itu dijalankan. Jadi Anda tidak dapat menggunakannya misalnya dalam hal-hal seperti:
setvar() {
var_name=$1 var_value=$2
declare "$var_name=$var_value"
}
setvar foo bar
Karena itu akan mendeklarasikan foo
variabel lokal setvar
sehingga tidak akan berguna.
bash-4.2
menambahkan -g
opsi untuk declare
mendeklarasikan variabel global , tapi bukan itu yang kita inginkan karena kita setvar
akan menetapkan global var yang bertentangan dengan pemanggil jika pemanggil adalah fungsi, seperti di:
setvar() {
var_name=$1 var_value=$2
declare -g "$var_name=$var_value"
}
foo() {
local myvar
setvar myvar 'some value'
echo "1: $myvar"
}
foo
echo "2: $myvar"
yang akan menghasilkan:
1:
2: some value
Juga, perhatikan bahwa sementara declare
dipanggil declare
(sebenarnya bash
meminjam konsep dari typeset
builtin shell Korn ), jika variabel sudah ditetapkan, declare
tidak mendeklarasikan variabel baru dan cara tugas dilakukan tergantung pada jenis variabel.
Contohnya:
varname=foo
varvalue='([PATH=1000]=something)'
declare "$varname=$varvalue"
akan menghasilkan hasil yang berbeda (dan berpotensi memiliki efek samping buruk) jika varname
sebelumnya dinyatakan sebagai skalar , array , atau array asosiatif .
eval
cara itu salah. Anda memperluas$var_value
sebelum meneruskannya keeval
yang artinya akan ditafsirkan sebagai kode shell! (coba misalnya denganvar_value="';:(){ :|:&};:'"
)