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?
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?
Jawaban:
Ini karena shell memperluas variabel dalam baris perintah sebelum benar-benar menjalankan perintah dan pada saat itu variabel tidak ada. Jika Anda menggunakan
TEST=foo; echo $TEST
ini akan bekerja.
export
akan membuat variabel muncul di lingkungan perintah yang dieksekusi selanjutnya (untuk tentang bagaimana ini bekerja di bash lihat help export
). Jika Anda hanya perlu variabel untuk muncul di lingkungan satu perintah, gunakan apa yang Anda coba, yaitu:
TEST=foo your-application
$TEST
sebelum baris perintah dieksekusi. Setelah echo
berjalan (perhatikan juga bahwa echo
biasanya akan menerjemahkan ke perintah built-in shell dan tidak ke /bin/echo
) ia melihat set variabel di lingkungannya. Namun, echo $TEST
tidak memberi tahu echo
untuk mengeluarkan isi variabel TEST
dari lingkungannya. Ia memberi tahu shell untuk menjalankan echo
argumen menjadi apa pun yang saat ini ada dalam variabel yang disebut TEST
- dan itu adalah dua hal yang sangat berbeda.
var=value sh -c 'echo "$var"'
?
"… $var …"
) tetapi tidak di dalam tanda kutip tunggal (misalnya, '… $var …'
). Karena echo "$var"
ada di dalam tanda kutip tunggal, seluruh string akan diteruskan ke sh -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
var=value echo whatever
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
var=value sh -c 'echo "$var"'
Itu akan menjadi masalah lain. Di sini, kita meneruskan var=value
ke sh
perintah, dan sh
kebetulan menggunakan lingkungannya. Shell mengonversi masing-masing variabel yang mereka terima dari lingkungannya ke variabel shell, sehingga var
variabel lingkungan yang sh
diterima akan dikonversi ke $var
variabel, dan ketika itu diperluas di echo
baris perintah itu, itu akan menjadi echo value
. Karena lingkungan secara default diwarisi, echo
juga akan menerima var=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):
(var=value; echo "1: $var"); echo "2: $var"
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":
f() {
local var
var=value
echo "1: $var"
}
f
echo "2: $var"
Dengan zsh, Anda dapat menggunakan fungsi sebaris:
(){ local var=value; echo "1: $var"; }; echo "2: $var"
atau:
function { local var=value; echo "1: $var"; }; echo "2: $var"
Dengan bash dan zsh (tetapi bukan ash, pdksh atau AT&T ksh), trik ini juga berfungsi:
var=value eval 'echo "1: $var"'; echo "2: $var"
Varian yang bekerja dalam beberapa kerang lebih ( dash
, mksh
, yash
) tapi tidak zsh
(kecuali dalam sh
/ ksh
emulasi):
var=value command eval 'echo "1: $var"'; echo "2: $var"
(menggunakan command
di depan builtin khusus (di sini eval
) di shell POSIX menghapus keistimewaan mereka (di sini bahwa penugasan variabel dari mereka tetap berlaku setelah mereka kembali))
Anda melakukannya dengan benar, tetapi sintaks bash adalah mudah untuk salah menafsirkan: Anda bisa berpikir bahwa echo $TEST
menyebabkan echo
untuk mengambil TEST
env var kemudian mencetaknya, tidak. Jadi diberikan
export TEST=123
kemudian
TEST=456 echo $TEST
melibatkan urutan berikut:
Shell mem-parsing seluruh baris perintah dan mengeksekusi semua penggantian variabel, sehingga baris perintah menjadi
TEST=456 echo 123
Itu menciptakan vars temp ditetapkan sebelum perintah, sehingga menyimpan nilai saat ini TEST
dan menimpanya dengan 456; baris perintah sekarang
echo 123
Ini 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:
>> export TEST=123
>> printenv TEST
123
>> TEST=456 printenv TEST
456
>> printenv TEST && TEST=456 printenv TEST && TEST=789 printenv TEST && printenv TEST
123
456
789
123
>>
printenv
bermanfaat untuk menguji / membuktikan konsep (berperilaku seperti naskah, berlawanan dengan echo
)
Anda bisa membuatnya bekerja dengan menggunakan:
TEST=foo && echo $TEST
TEST=foo
dijalankan sebagai pernyataan terpisah - tidak hanya diatur dalam konteks echo
.