Pertanyaan Bagaimana cara mencetak / gema variabel lingkungan?


Bagaimana cara mencetak variabel lingkungan yang baru saja diatur?

NAME=sam echo "$NAME" # empty

Anda bisa lihat di sini menggunakan eval berhasil. Apakah ini caranya?

NAME=sam eval 'echo $NAME' # => sam

22
2017-10-14 19:35


asal


Jawaban:


Ini harus pergi sebagai perintah yang berbeda misalnya:

NAME=sam; echo "$NAME"
NAME=sam && echo "$NAME"

Pengembangan $NAME untuk mengosongkan string dilakukan oleh shell tadi, sebelum dijalankan echo, jadi pada saat itu NAME variabel diteruskan ke echo lingkungan perintah, ekspansi sudah dilakukan (ke string nol).

Untuk mendapatkan hasil yang sama dalam satu perintah:

NAME=sam printenv NAME

26
2017-10-14 19:38



Sintaksnya

variable=value command

sering digunakan untuk mengatur variabel lingkungan untuk proses tertentu. Namun, Anda harus memahami proses mana yang mendapat variabel apa dan siapa yang menafsirkannya. Sebagai contoh, menggunakan dua cangkang:

a=5
# variable expansion by the current shell:
a=3 bash -c "echo $a"
# variable expansion by the second shell:
a=3 bash -c 'echo $a'

Hasilnya akan menjadi 5 untuk gema pertama dan 3 untuk yang kedua.


2
2017-10-15 15:41



Ini bekerja juga, dengan titik koma.

NAME=sam; echo $NAME


2
2017-10-14 19:38



Untuk membawa jawaban yang ada bersama dengan klarifikasi penting:

Seperti yang disebutkan, masalah dengan NAME=sam echo "$NAME" Apakah itu $NAME Diperluas oleh shell saat ini sebelum tugas NAME=sam berlaku.

Solusi yang melestarikan semantik asli (dari solusi solusi (tidak efektif) NAME=sam echo "$NAME"):

Gunakan juga eval[1]  (seperti dalam pertanyaan itu sendiri), atau printenv (sebagaimana ditambahkan oleh Aaron McDaid ke jawaban heemayl), atau bash -c (dari Jawaban Ljm Dullaart), dalam urutan efisiensi yang menurun:

NAME=sam eval 'echo "$NAME"'  # use `eval` only if you fully control the command string
NAME=sam printenv NAME
NAME=sam bash -c 'echo "$NAME"'

printenv bukan utilitas POSIX, tetapi tersedia di Linux dan macOS / BSD.

Apa gaya doa ini (<var>=<name> cmd ...) adalah mendefinisikan NAME:

  • sebagai lingkungan Hidup variabel 
  • itu adalah hanya ditentukan untuk perintah yang dipanggil.

Dengan kata lain: NAME hanya ada untuk perintah yang dipanggil, dan tidak berpengaruh pada shell saat ini (jika tidak ada variabel bernama NAME sudah ada sebelumnya, tidak akan ada sesudahnya; yang sudah ada sebelumnya NAME variabel tetap tidak berubah).

POSIX mendefinisikan aturan-aturan untuk jenis doa semacam ini di dalamnya Pencarian dan Eksekusi Perintah bab.


Solusi berikut bekerja dengan sangat berbeda (dari jawaban heemayl):

NAME=sam; echo "$NAME"
NAME=sam && echo "$NAME"

Sementara mereka menghasilkan yang sama keluaran, mereka malah mendefinisikan:

  • Sebuah kulit variabel NAME (hanya) daripada lingkungan Hidup variabel
    • jika echo adalah perintah yang diandalkan lingkungan Hidup variabel NAME, itu tidak akan didefinisikan (atau berpotensi didefinisikan berbeda dari sebelumnya).
  • bahwa tinggal di setelah perintah.

Perhatikan bahwa setiap variabel lingkungan juga terekspos sebagai variabel shell, tetapi inversenya tidak benar: variabel shell hanya terlihat oleh shell saat ini dan subkelopenya, tetapi tidak untuk proses anak, seperti utilitas eksternal dan skrip (tidak bersumber) (kecuali mereka ditandai sebagai variabel lingkungan dengan export atau declare -x).


[1] Secara teknis, bash melanggar POSIX di sini (seperti ini zsh): Sejak eval adalah khusus shell built-in, yang sebelumnya NAME=sam penugasan harus menyebabkan variabel $NAME untuk tetap dalam lingkup setelah perintah selesai, tetapi bukan itu yang terjadi.
Namun, saat Anda berlari bash dalam mode kompatibilitas POSIX, itu aku s patuh.
dash dan ksh selalu sesuai.
Aturan yang tepat rumit, dan beberapa aspek diserahkan kepada implementasi untuk diputuskan; lagi, lihat Pencarian dan Eksekusi Perintah.


2
2017-10-15 16:12