Jika saya lari
export TEST=foo
echo $TEST
Ini menghasilkan foo.
Jika saya lari
TEST=foo echo $TEST
Itu tidak. Bagaimana saya bisa mendapatkan fungsionalitas ini tanpa menggunakan ekspor atau skrip?
shell
environment-variables
echo
ashleysmithgpu
sumber
sumber
Jawaban:
Ini karena shell memperluas variabel dalam baris perintah sebelum benar-benar menjalankan perintah dan pada saat itu variabel tidak ada. Jika Anda menggunakan
ini akan bekerja.
export
akan membuat variabel muncul di lingkungan perintah yang dieksekusi selanjutnya (untuk tentang bagaimana ini bekerja di bash lihathelp export
). Jika Anda hanya perlu variabel untuk muncul di lingkungan satu perintah, gunakan apa yang Anda coba, yaitu:sumber
$TEST
sebelum baris perintah dieksekusi. Setelahecho
berjalan (perhatikan juga bahwaecho
biasanya akan menerjemahkan ke perintah built-in shell dan tidak ke/bin/echo
) ia melihat set variabel di lingkungannya. Namun,echo $TEST
tidak memberi tahuecho
untuk mengeluarkan isi variabelTEST
dari lingkungannya. Ia memberi tahu shell untuk menjalankanecho
argumen menjadi apa pun yang saat ini ada dalam variabel yang disebutTEST
- dan itu adalah dua hal yang sangat berbeda.var=value sh -c 'echo "$var"'
?"… $var …"
) tetapi tidak di dalam tanda kutip tunggal (misalnya,'… $var …'
). Karenaecho "$var"
ada di dalam tanda kutip tunggal, seluruh string akan diteruskan kesh -c
shell ( ) baru tanpa ditafsirkan oleh shell interaktif luar. … (Lanjutan)sh -c
kulit anak baru ( ).Saya menduga Anda ingin memiliki variabel shell untuk memiliki cakupan terbatas, daripada variabel lingkungan. Variabel lingkungan adalah daftar string yang diteruskan ke perintah ketika dieksekusi .
Di
Anda meneruskan
var=value
string ke lingkungan yang menerima gema. Namun,echo
tidak melakukan apa-apa dengan daftar lingkungannya dan tetap di sebagian besar shell,echo
dibangun dan karenanya tidak dieksekusi .Jika Anda telah menulis
Itu akan menjadi masalah lain. Di sini, kita meneruskan
var=value
kesh
perintah, dansh
kebetulan menggunakan lingkungannya. Shell mengonversi masing-masing variabel yang mereka terima dari lingkungannya ke variabel shell, sehinggavar
variabel lingkungan yangsh
diterima akan dikonversi ke$var
variabel, dan ketika itu diperluas diecho
baris perintah itu, itu akan menjadiecho value
. Karena lingkungan secara default diwarisi,echo
juga akan menerimavar=value
di lingkungannya (atau akan jika itu dijalankan), tetapi sekali lagi,echo
tidak peduli dengan lingkungan.Sekarang, jika seperti yang saya duga, yang Anda inginkan adalah membatasi ruang lingkup variabel shell, ada beberapa pendekatan yang mungkin.
Portably (Bourne dan POSIX):
The (...) di atas memulai sub-shell (proses shell baru di sebagian besar shell), jadi variabel apa pun yang dideklarasikan hanya akan mempengaruhi sub-shell itu, jadi saya berharap kode di atas menghasilkan output "1: value" dan "2:" atau "2: apa pun-var-sudah-ditetapkan-sebelumnya".
Dengan sebagian besar shell mirip Bourne, Anda dapat menggunakan fungsi dan builtin "lokal":
Dengan zsh, Anda dapat menggunakan fungsi sebaris:
atau:
Dengan bash dan zsh (tetapi bukan ash, pdksh atau AT&T ksh), trik ini juga berfungsi:
Varian yang bekerja dalam beberapa kerang lebih (
dash
,mksh
,yash
) tapi tidakzsh
(kecuali dalamsh
/ksh
emulasi):(menggunakan
command
di depan builtin khusus (di sinieval
) di shell POSIX menghapus keistimewaan mereka (di sini bahwa penugasan variabel dari mereka tetap berlaku setelah mereka kembali))sumber
Anda melakukannya dengan benar, tetapi sintaks bash adalah mudah untuk salah menafsirkan: Anda bisa berpikir bahwa
echo $TEST
menyebabkanecho
untuk mengambilTEST
env var kemudian mencetaknya, tidak. Jadi diberikankemudian
melibatkan urutan berikut:
Shell mem-parsing seluruh baris perintah dan mengeksekusi semua penggantian variabel, sehingga baris perintah menjadi
Itu menciptakan vars temp ditetapkan sebelum perintah, sehingga menyimpan nilai saat ini
TEST
dan menimpanya dengan 456; baris perintah sekarangIni mengeksekusi perintah yang tersisa, yang dalam hal ini mencetak 123 ke stdout (jadi perintah shell yang tetap bahkan tidak menggunakan nilai temp dari
TEST
)Ini mengembalikan nilai
TEST
Gunakan printenv sebagai gantinya, karena tidak melibatkan substitusi variabel:
sumber
printenv
bermanfaat untuk menguji / membuktikan konsep (berperilaku seperti naskah, berlawanan denganecho
)Anda bisa membuatnya bekerja dengan menggunakan:
sumber
TEST=foo
dijalankan sebagai pernyataan terpisah - tidak hanya diatur dalam konteksecho
.