Ketika saya mengerti maksud Anda, saya tidak percaya bahwa salah satu dari jawaban ini benar. evaltidak perlu dengan cara apa pun, Anda juga tidak perlu bahkan dua kali mengevaluasi variabel Anda.
Memang benar, @Gilles sangat dekat, tetapi dia tidak membahas masalah kemungkinan nilai-nilai utama dan bagaimana mereka harus digunakan jika Anda membutuhkannya lebih dari sekali. Lagi pula, templat harus digunakan lebih dari sekali, bukan?
Saya pikir ini lebih merupakan urutan di mana Anda mengevaluasi mereka yang penting. Pertimbangkan yang berikut ini:
TERATAS
Di sini Anda akan menetapkan beberapa default dan bersiap untuk mencetaknya saat dipanggil ...
#!/bin/sh
_top_of_script_pr() (
IFS="$nl" ; set -f #only split at newlines and don't expand paths
printf %s\\n ${strings}
) 3<<-TEMPLATES
${nl=
}
${PLACE:="your mother's house"}
${EVENT:="the unspeakable."}
${ACTION:="heroin"}
${RESULT:="succeed."}
${strings:="
I went to ${PLACE} and saw ${EVENT}
If you do ${ACTION} you will ${RESULT}
"}
#END
TEMPLATES
TENGAH
Di sinilah Anda mendefinisikan fungsi lain untuk memanggil fungsi cetak Anda berdasarkan hasil mereka ...
EVENT="Disney on Ice."
_more_important_function() { #...some logic...
[ $((1+one)) -ne 2 ] && ACTION="remedial mathematics"
_top_of_script_pr
}
_less_important_function() { #...more logic...
one=2
: "${ACTION:="calligraphy"}"
_top_of_script_pr
}
BAWAH
Anda telah menyiapkan semuanya sekarang, jadi di sinilah Anda akan menjalankan dan menarik hasil Anda.
_less_important_function
: "${PLACE:="the cemetery"}"
_more_important_function
: "${RESULT:="regret it."}"
_less_important_function
HASIL
Saya akan membahas mengapa suatu saat, tetapi menjalankan di atas menghasilkan hasil sebagai berikut:
_less_important_function()'s Lari pertama:
Saya pergi ke rumah ibumu dan melihat Disney on Ice.
Jika Anda melakukan kaligrafi, Anda akan berhasil.
kemudian _more_important_function():
Saya pergi ke kuburan dan melihat Disney on Ice.
Jika Anda melakukan matematika perbaikan Anda akan berhasil.
_less_important_function() lagi:
Saya pergi ke kuburan dan melihat Disney on Ice.
Jika Anda melakukan matematika perbaikan Anda akan menyesalinya.
BAGAIMANA ITU BEKERJA:
Fitur utama di sini adalah konsep conditional ${parameter} expansion.Anda dapat mengatur variabel ke nilai hanya jika tidak disetel atau null menggunakan formulir:
${var_name: =desired_value}
Jika Anda hanya ingin menetapkan variabel yang tidak disetel, Anda akan menghilangkan :colondan nilai-nilai nol akan tetap apa adanya.
TENTANG RUANG LINGKUP:
Anda mungkin memperhatikan bahwa dalam contoh di atas $PLACEdan $RESULTdiubah ketika diatur melalui parameter expansionmeskipun _top_of_script_pr()telah dipanggil, mungkin pengaturan mereka ketika dijalankan. Alasan karya ini adalah bahwa _top_of_script_pr()adalah ( subshelled )fungsi - Saya sertakan dalam parensdaripada { curly braces }yang digunakan untuk orang lain. Karena itu disebut dalam subkulit, setiap variabel yang disetel adalah locally scopeddan saat ia kembali ke shell induknya, nilai-nilai itu menghilang.
Tetapi ketika _more_important_function()set $ACTIONitu globally scopedbegitu mempengaruhi _less_important_function()'sevaluasi kedua $ACTIONkarena _less_important_function()set $ACTIONhanya melalui${parameter:=expansion}.
:BATAL
Dan mengapa saya menggunakan :colon?Yah terkemuka , manhalaman akan memberitahu Anda bahwa : does nothing, gracefully.Anda lihat, parameter expansionpersis seperti apa kedengarannya - itu expandsdengan nilai ${parameter}.Jadi ketika kita mengatur variabel dengan ${parameter:=expansion}kita pergi dengan nilainya - yang shell akan upaya untuk mengeksekusi in-line. Jika ia mencoba menjalankannya, the cemeteryia hanya akan meludahkan beberapa kesalahan pada Anda. PLACE="${PLACE:="the cemetery"}"akan menghasilkan hasil yang sama, tetapi juga berlebihan dalam hal ini dan saya lebih suka shell: ${did:=nothing, gracefully}.
Itu memungkinkan Anda untuk melakukan ini:
echo ${var:=something or other}
echo $var
something or other
something or other
DI SINI-DOKUMEN
Dan omong-omong - definisi in-line dari variabel nol atau tidak disetel juga mengapa yang berikut ini berfungsi:
<<HEREDOC echo $yo
${yo=yoyo}
HEREDOC
yoyo
Cara terbaik untuk memikirkan here-document adalah sebagai file aktual yang dialirkan ke file-deskriptor input. Kurang lebih seperti itu, tetapi cangkang yang berbeda menerapkannya sedikit berbeda.
Dalam kasus apa pun, jika Anda tidak mengutip, <<LIMITERAnda dapat mengalirkannya dan mengevaluasi untuk expansion.Jadi mendeklarasikan variabel dalam sebuah here-documentcan dapat berfungsi, tetapi hanya melalui expansionyang membatasi Anda untuk menetapkan hanya variabel yang belum ditetapkan. Namun, itu sangat sesuai dengan kebutuhan Anda seperti yang telah Anda gambarkan, karena nilai default Anda akan selalu ditetapkan ketika Anda memanggil fungsi cetak template Anda.
KENAPA TIDAK eval?
Nah, contoh yang saya sajikan memberikan cara yang aman dan efektif untuk menerima parameters.Karena menangani ruang lingkup, setiap variabel dalam set via ${parameter:=expansion}dapat didefinisikan dari luar. Jadi, jika Anda meletakkan semua ini dalam skrip yang disebut template_pr.sh dan jalankan:
% RESULT=something_else template_pr.sh
Anda akan mendapatkan:
Saya pergi ke rumah ibumu dan melihat Disney on Ice
Jika Anda melakukan kaligrafi, Anda akan melakukan sesuatu
Saya pergi ke kuburan dan melihat Disney on Ice
Jika Anda melakukan perbaikan matematika Anda akan something_else
Saya pergi ke kuburan dan melihat Disney on Ice
Jika Anda melakukan perbaikan matematika Anda akan something_else
Ini tidak akan berfungsi untuk variabel-variabel yang secara harfiah diatur dalam skrip, seperti $EVENT, $ACTION,dan$one, tetapi saya hanya mendefinisikan mereka dengan cara itu untuk menunjukkan perbedaannya.
Dalam kasus apa pun, penerimaan input yang tidak diketahui ke dalam suatu evaledpernyataan pada dasarnya tidak aman, sedangkan parameter expansionsecara khusus dirancang untuk melakukannya.