Saat menulis beberapa kode saya menemukan bahwa baris ini:
$ TZ="America/Los_Angeles" date; echo "$TZ"
Thu Dec 24 14:39:15 PST 2015
Benar memberikan waktu aktual di "Los Angeles" dan bahwa nilai variabel TZ
tidak dipertahankan. Semua seperti yang diharapkan.
Namun, dengan baris ini, yang saya gunakan untuk memperluas beberapa format hingga saat ini, dan yang pada dasarnya mengeksekusi hal yang sama, mempertahankan nilai TZ:
TZ="America/Los_Angeles" eval date; echo "$TZ"
Thu Dec 24 14:41:34 PST 2015
America/Los_Angeles
Setelah beberapa tes lagi, saya mengetahui bahwa ini hanya terjadi pada beberapa shell. Ini terjadi di dash, ksh tetapi tidak di bash atau zsh.
Q's
Pertanyaannya adalah:
- Mengapa nilai TZ dipertahankan dalam shell ini?
- Bagaimana itu bisa dihindari / dikendalikan (jika mungkin)?
Tambahan.
Saya menjalankan beberapa tes dengan dua baris ini:
myTZ="America/Los_Angeles"
unset TZ; { TZ="$myTZ" date; } >/dev/null; echo -n " direct $TZ"
unset TZ; { TZ="$myTZ" eval date; } >/dev/null; echo " evaled $TZ"
Dan ini menghasilkan:
/bin/ash : direct evaled America/Los_Angeles
/bin/dash : direct evaled America/Los_Angeles
/bin/sh : direct evaled America/Los_Angeles
/bin/bash : direct evaled
/bin/ksh93 : direct evaled America/Los_Angeles
/bin/lksh : direct evaled America/Los_Angeles
/bin/mksh : direct evaled America/Los_Angeles
/bin/zsh : direct evaled
/bin/zsh4 : direct evaled
Nilai TZ memengaruhi running shell di semua shell kecuali bash dan zsh.
Ternyata ada alasan yang sangat spesifik untuk perilaku ini.
Deskripsi tentang apa yang terjadi sedikit lebih lama.
Hanya penugasan.
Baris perintah yang dibuat (hanya) dari penugasan akan mengatur variabel untuk shell ini .
Nilai vars yang ditugaskan akan dipertahankan.
Perintah eksternal.
Tugas sebelum variabel set perintah eksternal untuk itu shell hanya:
Dan maksud saya "eksternal" sebagai perintah yang harus dicari di PATH.
Ini juga berlaku untuk built-in normal (seperti cd, misalnya):
Sampai disini semua seperti yang biasanya diharapkan.
Built-In Khusus.
Tetapi untuk built-in khusus, POSIX mensyaratkan bahwa nilai ditetapkan untuk shell ini .
Saya menggunakan panggilan untuk
sh
menganggap itush
adalah shell yang sesuai dengan POSIX.Ini bukan sesuatu yang biasanya digunakan.
Ini berarti bahwa penugasan ditempatkan di depan daftar built-in khusus ini akan mempertahankan nilai yang ditetapkan dalam shell yang sedang berjalan:
Ini akan terjadi jika shell berfungsi sesuai dengan spesifikasi POSIX.
Kesimpulan:
Dimungkinkan untuk mengatur variabel hanya untuk satu perintah, perintah apa saja, dengan memastikan bahwa perintah tersebut bukan built-in khusus. Perintahnya
command
adalah builtin reguler. Ia hanya memberi tahu shell untuk menggunakan perintah, bukan fungsi. Baris ini bekerja di semua shell (kecuali ksh93):Dalam hal demikian vars a dan b diatur untuk lingkungan perintah perintah, dan dibuang setelah itu.
Sebagai gantinya, ini akan mempertahankan nilai yang ditetapkan (kecuali bash dan zsh):
Perhatikan bahwa tugas setelah eval adalah tanda kutip tunggal untuk melindunginya dari ekspansi yang tidak diinginkan.
Jadi: Untuk menempatkan variabel dalam lingkungan perintah, gunakan
command eval
:sumber