Perbedaan antara ekspansi dan substitusi dalam terminologi scripting shell

8

Ekspansi dan Substitusi tampaknya saling bertukar pada konteks yang sama dalam bahasa pemrograman shell. Misalnya, beberapa dokumen seperti manual referensi Bash , Bash Hackers Wiki menggunakan kata 'ekspansi' untuk menjelaskan ' ekspansi parameter shell '. Namun, beberapa dokumen lain sepertinya lebih menyukai kata 'substitusi'. Panduan Bash-Scripting Lanjutan menggunakan substituion parameter .

Apakah ada perbedaan antara 'ekspansi' dan 'substitusi' dalam hal terminologi pemrograman shell?

MS.Kim
sumber
Keduanya berlaku dalam konteks yang berbeda, misalnya variable expansion, command substitution. Apa keraguanmu?
devnull
Tanpa konteks tertentu, saya khawatir ini terlalu luas dan tidak jelas .
devnull
Melihat halaman bash man, secara umum kata "ekspansi" tampaknya digunakan jika hanya hal-hal internal shell yang terlibat, sementara "substitusi" tampaknya lebih disukai untuk hal-hal yang melibatkan proses eksternal.
celtschk
Jika Anda menerima saran saya, Anda akan berhenti membaca dokumen-dokumen itu sampai Anda benar-benar akrab dengan ini: pubs.opengroup.org/onlinepubs/9699919799/utilities/… Ketika Anda selesai dengan yang Anda lakukan man shdan man set. Dan ketika Anda memiliki hal-hal itu, maka Anda melakukan dokumen khusus shell.
mikeserv
@ Devnull Anda benar. Meskipun saya meletakkan tautan untuk konteks, akan lebih baik untuk menentukan konteks secara eksplisit dengan pertanyaan. Saya akan mengedit pertanyaan sehingga orang dapat memahaminya dengan jelas.
MS.Kim

Jawaban:

6

Pergantian hampir identik dengan ekspansi dalam konteks ini karena maknanya tumpang tindih. Tidak satu pun sub kategori yang cukup lengkap dari yang lain, meskipun di bagian Manual GNU Anda referensi ada substitusi yang dianggap sebagai bagian dari ekspansi keseluruhan.

Sebuah ekspansi adalah penggalian nilai sebuah identifier. Misal, jika this=that, saat kami berkembang, thiskami mendapatkannya that. Perluasan yang tidak melibatkan substitusi ditentukan sebelumnya bahwa nilai yang digunakan sudah ada dan harus diambil, meskipun ini termasuk menggabungkan nilai yang didapat / nilai eksplisit (seperti dengan "ekspansi aritmatika").

Sebuah substitusi menciptakan nilai sebagai hasil dari operasi input / output eksplisit. Misalnya, jika this=$(foo bar), thisadalah hasil dari mengeksekusi foo bardan menangkap outputnya. 1 Meskipun nilai yang dihasilkan dari substitusi mungkin benar-benar dapat diprediksi, nilai ini berbeda dari yang diperoleh dalam ekspansi normal karena tidak benar-benar ada sampai substitusi terjadi - itu diproduksi.

Substitusi datang dalam dua rasa, perintah dan proses , yang agak simetris:

# Command substitution
foo=$(ls)
# Process substitution
wc <(ls)

"Perintah" di yang pertama adalah ls, seperti "proses" di yang kedua. Kita dapat mengatakan apa yang diganti sebenarnya adalah ujung pipa. Substitusi proses tumpang tindih dengan pengalihan . Namun, ini mungkin agak terlalu di bawah batas teknis secara teknis, yang membawa kita ke catatan kaki ...


  1. foo bardalam hal ini bisa menjadi fungsi shell internal, dalam hal ini tidak ada IO interprocess. Keberadaan shell built-in kurang jelas mengaburkan perbedaan ini. Dalam hal konten, input dan output akan sama.
goldilocks
sumber
Saya suka penjelasan ini, tetapi bagaimana kita menyamakannya dengan ekspansi nama file , yang tentu saja menghasilkan seperangkat nama file sebagai hasil dari operasi (algoritma pencocokan).
De Novo
Tentu, tetapi untuk bermain semantik, bukankah "mengekstraksi nilai pengidentifikasi" (apa yang saya sebut ekspansi) juga merupakan operasi, oleh karena itu substitusi? Terutama karena "ada pergantian yang dianggap bagian dari ekspansi keseluruhan". Yaitu, hubungan antara kata-kata ini tidak analog dengan perbedaan antara kiri dan kanan. Saya pikir ekspansi nama file sesuai dengan definisi asli saya tentang ekspansi dengan baik, tetapi saya telah mengklarifikasi hal-hal tentang penggantian di atas untuk membantu membuatnya lebih jelas mengapa bukan itu.
goldilocks
Masalah saya mengkuadratkan penjelasan intuitif ini dengan ekspansi nama file bukan karena saya ingin istilah tersebut didefinisikan secara eksklusif, tetapi bahwa perluasan nama file tampaknya tidak mengambil nilai yang terikat pada pengenal. Di dalam cangkang tertentu, nilai untuk bola tertentu akan bergantung pada lebih dari sekadar bola, dan bola yang sama dapat menghasilkan output yang berbeda dalam konteks yang berbeda. Lebih lanjut, tidak perlu untuk mengikat nilai untuk mengambilnya nanti. Hubungannya tidak sewenang-wenang (seperti dalam foo = "apa pun yang Anda inginkan"; echo "$ foo"), melainkan perhitungan dan hasil.
De Novo
Saya kira hubungan antara ekspresi dan nilai dalam ekspansi aritmatika juga tidak (tepat) sewenang-wenang, tetapi pasti hanya ada satu nilai untuk ekspansi yang diberikan, terlepas dari konteksnya. Saya mungkin hanya nitpicking di sini, tetapi dari semua ekspansi shell, ekspansi nama file tampaknya menjadi orang aneh, mengingat penjelasan ini.
De Novo
2
set -- arg arg2
echo ${2+"$1"}
 #OUTPUT 
arg

shift
echo ${2+"$1"}
 #OUTPUT

 #there doesn't seem to be anything here

Saya pikir perbedaannya pada umumnya terlalu kecil untuk diperhatikan - dan istilah ini sering digunakan secara bergantian. Meskipun, jika Anda melihat di atas dua kasus, Anda dapat melihat bahwa dalam contoh kita pertama pengganti $1 untuk $2sebagai akibat dari ekspansi dari $2. Segera setelah $2tidak dapat diperluas tidak ada substitusi.

goldilocks membuat poin yang bagus tentang keberadaan substitusi yang halus. Sepertinya kucing Schrodinger, kurasa. Itu mengingatkan saya pada sesuatu. Anda mungkin tidak terbiasa dengan bentuk ekspansi parameter yang ditentukan POSIX ini, tetapi ia bekerja dengan cara yang berlawanan dengan bentuk di atas:

${var:?if $var is unset or null its \
     parent shell dies and this message is output to stderr}

Sekarang terkadang saya menginginkan perilaku yang sama tetapi untuk setnilai. POSIX tidak menentukan perilaku itu untuk apa pun secara tepat. Tapi, dengan satu atau dua trik, itu berhasil:

N= #N is null
var="any value should fail"
${var:+${N:?we substitute our \$Null var when \$var is expanded}}
  #OUTPUT
sh: line 3: N: we substitute our $Null var when $var is expanded

Tapi:

N= #N is null
var=
${var:+${N:?is never substituted}}
  #OUTPUT

#there doesn't seem to be anything here
mikeserv
sumber