Manual Bash mengatakan:
Substitusi perintah, perintah yang dikelompokkan dengan tanda kurung, dan perintah asinkron dipanggil dalam lingkungan subkulit yang merupakan duplikat dari lingkungan shell,
kecuali jebakan yang ditangkap oleh shell direset ke nilai yang diwarisi shell dari induknya di doa.
Dalam contoh ini,b
bukan variabel lingkungan, jadi b
tidak ada di subkulit yang dibuat oleh substitusi perintah. Lalu mengapa c
diberi nilai b
dengan substitusi perintah? Apakah karena ekspansi parameter terjadi untuk $b
dalam proses shell sebelum membuat subkulit untuk mengeksekusi echo 1
?
$ b=1
$ c=$(echo $b)
$ echo $c
1
Jawaban yang Diterima:
Tidak, subkulit dibuat terlebih dahulu.
Lingkungan eksekusi shell berisi parameter shell yang ditetapkan oleh penetapan variabel dan variabel lingkungan. Lingkungan subkulit dibuat dengan menduplikasi lingkungan shell, sehingga berisi semua variabel dari lingkungan shell saat ini.
Lihat contohnya:
$ b=1
$ c=$(b=2; echo "$b")
$ echo "$c"
2
Outputnya adalah 2
bukannya 1
.
Lingkungan subkulit yang dibuat dengan substitusi perintah berbeda dengan lingkungan shell yang dibuat dengan memanggil shell yang dapat dieksekusi.
Saat Anda memanggil shell sebagai:
$ bash -c :
shell saat ini menggunakan execve() untuk membuat proses shell baru, seperti:
execve("/bin/bash", ["bash", "-c", ":"], [/* 64 vars */]) = 0
argumen terakhir diteruskan ke execve
berisi semua variabel lingkungan.
Itulah mengapa Anda perlu mengekspor variabel untuk mendorongnya ke variabel lingkungan, yang akan disertakan dalam perintah yang dijalankan selanjutnya:
$ a=; export a
$ strace -e execve bash -c :
execve("/bin/bash", ["bash", "-c", ":"], [/* 65 vars */]) = 0
+++ exited with 0 +++
Perhatikan variabel lingkungan berubah dari 64 menjadi 65. Dan variabel yang tidak diekspor tidak akan diteruskan ke lingkungan shell baru:
$ a=; b=; export a
$ strace -e execve bash -c :
execve("/bin/bash", ["bash", "-c", ":"], [/* 65 vars */]) = 0
+++ exited with 0 +++
Perhatikan variabel lingkungan masih 65.
Dalam substitusi perintah, shell menggunakan fork() untuk membuat proses shell baru, yang baru saja menyalin lingkungan shell saat ini – yang berisi kumpulan variabel dan variabel lingkungan.