Apakah $ () sebuah subkulit?


Jawaban:


75

$(…)adalah subkulit menurut definisi: ini adalah salinan dari kondisi runtime shell¹, dan perubahan pada status yang dibuat dalam subkulit tidak memiliki dampak pada induk. Subkulit biasanya diimplementasikan dengan forking proses baru (tetapi beberapa shell dapat mengoptimalkan ini dalam beberapa kasus).

Itu bukan subkulit tempat Anda dapat mengambil nilai variabel. Jika perubahan variabel berdampak pada induk, itu tidak akan menjadi subkulit. Ini adalah subkulit yang outputnya dapat diambil orang tua. Subkulit yang dibuat oleh $(…)memiliki output standar yang diatur ke pipa, dan induk membaca dari pipa itu dan mengumpulkan output.

Ada beberapa konstruksi lain yang membuat subkulit. Saya pikir ini adalah daftar lengkap untuk bash:

  • Subshell untuk pengelompokan : ( … )tidak melakukan apa-apa selain membuat subkulit dan menunggu itu berakhir). Kontras dengan { … }perintah grup mana yang murni untuk tujuan sintaksis dan tidak membuat subkulit.
  • Latar Belakang : … &membuat subkulit dan tidak menunggu itu berakhir.
  • Pipeline : … | …membuat dua subkulit, satu untuk sisi kiri dan satu untuk sisi kanan, dan menunggu keduanya berakhir. Shell membuat pipa dan menghubungkan output standar sisi kiri ke ujung penulisan pipa dan input standar sisi kanan ke ujung read. Dalam beberapa shell (ksh88, ksh93, zsh, bash dengan set lastpipeopsi dan efektif), sisi kanan berjalan di shell asli, sehingga konstruksi pipa hanya menciptakan satu subkulit.
  • Substitusi perintah : $(…)(juga dieja `…`) membuat subkulit dengan output standarnya disetel ke pipa, mengumpulkan output di induknya dan memperluas ke output itu, dikurangi garis turunya yang tertinggal. (Dan hasilnya mungkin lebih lanjut akan terpecah dan menggumpal, tapi itu cerita lain.)
  • Substitusi proses : <(…)membuat subkulit dengan output standar yang disetel ke pipa dan mengembang ke nama pipa. Induk (atau proses lain) dapat membuka pipa untuk berkomunikasi dengan subkulit. >(…)melakukan hal yang sama tetapi dengan pipa pada input standar.
  • Coprocess : coproc …membuat subkulit dan tidak menunggu itu berakhir. Input dan output standar subkulit masing-masing diatur ke pipa dengan induk yang terhubung ke ujung masing-masing pipa.

¹ Berbeda dengan menjalankan shell yang terpisah .


Bisakah Anda juga memasukkan ${...}dalam jawabannya?
user1717828

3
@ user1717828 Apa? Mengapa? Apa hubungannya ekspansi variabel dari jarak jauh dengan pertanyaan ini? Saya tidak akan memasukkan seluruh manual shell dalam jawaban saya.
Gilles 'SANGAT berhenti menjadi jahat'

1
Apa hubungannya ekspansi variabel dari jarak jauh dengan pertanyaan ini? Saya tidak tahu, itu sebabnya saya bertanya :-) Jadi saya kira substitusi kurung kurawal tidak seperti substitusi kurung kurung.
user1717828

@ user1717828: ekspansi variabel tidak terkait dengan subkulit; itu adalah mekanisme yang terpisah sama sekali, dan pasti layak dibaca jika Anda baru memulai!
0xdd

1
@ EnricoMariaDeAngelis Ini bukan satu-satunya cara, tapi itu cara yang paling alami. Cara lain adalah command | { read line; … }(tergantung pada shell, linemungkin atau mungkin tidak tersedia setelah pipa). Semua cara melibatkan subkulit karena perintah yang menghasilkan output harus berjalan secara independen dari shell yang membaca input. Jika perintah itu murni internal ke shell (hanya shell yang dibangun dan dibangun, tidak ada perintah eksternal), shell mungkin tidak membuat subproses, tapi itu hanya optimasi, itu masih membuat subkulit.
Gilles 'SANGAT berhenti menjadi jahat'

20

Dari halaman manual bash (1) di bash versi 4.4, bagian "EXPANSION", subbagian "Command Substitution":

Bash melakukan ekspansi dengan mengeksekusi commanddi lingkungan subkulit [...]



1
Menariknya, di bawah CentOS 7 halaman bashmanual tidak menyebutkan subshell: Bash performs the expansion by executing command and replacing the command substitution with the standard output of the command, with any trailing newlines deleted.Saya ingin tahu apakah ini adalah penghilangan yang disengaja.
dr01

6
@ dr01 Sebaliknya, bash 4.4 mengubah kata-kata dari kalimat itu menjadi kata “subshell”. Itu adalah klarifikasi: manual secara eksplisit menyebutkan bahwa berbagai konstruksi lainnya adalah subkulit, tetapi sampai 4.4 tidak secara eksplisit dinyatakan untuk substitusi perintah.
Gilles 'SANGAT berhenti menjadi jahat'

Yap, pada CentOS v7.4.1708 (cukup baru) bash adalah v4.2.46.
dr01

5

Ya, ( commands... )adalah bashsubkulit yang akan dijalankan commands...dalam proses lain.

Satu-satunya perbedaan ketika Anda miliki $( commands... )adalah bahwa bagian kode ini setelah eksekusi commands...akan diganti dengan semua yang commands...ditulis stdout.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.