Apa variabel bentuk ini = $ (...)

9

Apa artinya yang berikut ini:

basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

Saya khususnya tertarik pada bagian ini:

varible=$(...)

Saya tahu bahwa tanda kurung digunakan untuk menjalankan subproses, tetapi bagaimana jika mereka digunakan bersama dengan $?

Maxim Koretskyi
sumber
3
Jika Anda menggunakan bash: Lihat ke halaman manual via man bashdan cari substitusi Command
FloHe

Jawaban:

16

Dari manual Bash ( man bash):

   Substitusi Perintah
       Substitusi perintah memungkinkan output dari suatu perintah untuk menggantikan
       nama perintah. Ada dua bentuk:

              $ (perintah)
       atau
              `perintah`

       Bash melakukan ekspansi dengan menjalankan perintah dalam sebuah subkulit
       lingkungan dan mengganti substitusi perintah dengan standar
       output dari perintah, dengan baris baru yang tertinggal dihapus. Tertanam
       baris baru tidak dihapus, tetapi mereka dapat dihapus selama kata
       pemisahan. Substitusi perintah $ (file cat) dapat diganti dengan
       setara tetapi lebih cepat $ (<file).

(Hal ini berlaku untuk semua Bourne-seperti kerang, yaitu sh, ksh, zsh, bashdll, dan zshjuga mampu data capture dengan tertanam karakter NUL dengan cara ini)

Perintah

basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

akan menetapkan nama direktori tempat skrip berada (sambil juga mengubah semua garis miring terbalik ke garis miring) ke variabel basedir. Kesalahan, peringatan, atau pesan diagnostik lainnya yang dikeluarkan ke aliran kesalahan standar masih akan ditampilkan di terminal ( $(...)hanya menangkap keluaran standar dari perintah).

Shell akan mulai dengan menjalankan substitusi perintah terdalam:

echo "$0" | sed -e 's,\\,/,g'

Output dari itu akan diberikan sebagai string dirname, dan output dari itu akan ditugaskan ke variabel basedir.

Kutipan ganda ada untuk memastikan bahwa tidak ada pemisahan kata atau penggumpalan nama file akan dilakukan, jika tidak, Anda mungkin menemukan bahwa skrip gagal atau menghasilkan output aneh ketika $0(nama skrip termasuk jalur yang digunakan untuk menjalankannya) berisi spasi karakter atau karakter globbing nama file (seperti ?atau *).

Secara umum adalah ide yang baik untuk selalu mengutip ekspansi (ekspansi variabel, penggantian perintah, dan ekspansi aritmatika). Lihat pertanyaan ini dan jawabannya untuk penjelasan yang bagus mengapa ini adalah ide yang bagus.

Jika skrip dieksekusi sebagai

$ /usr/local/bin/script.sh

maka basedirakan mendapatkan nilai /usr/local/bin.

Atau, di Cygwin:

$ bash c:\\Users\\Me\\script.sh

maka basedirakan mendapatkan nilai c:/Users/Me. Double backslash pada baris perintah dalam kasus ini hanya untuk menghindari backslash tunggal dari shell. Nilai aktual $0adalah c:\Users\Me\script.sh.

Cara lain untuk melakukan hal yang sama tanpa menggunakan dirname, echodan sedmungkin

basedir="${0//\\//}"
basedir="${basedir%/*}"
Kusalananda
sumber
terima kasih, jadi pada dasarnya mulai parsing dari kurung terdalam, benar? dan mengapa kutipan digunakan?
Maxim Koretskyi
@ Maximus Benar. Saya telah memperbarui jawaban saya dengan info lebih lanjut.
Kusalananda
Mungkin Anda harus mengatakan "berlaku untuk semua kerang mirip Bourne". Sedikit lebih jelas seperti itu
Sergiy Kolodyazhnyy
@Erg, perhatikan bahwa shell Bourne (seperti /bin/shSolaris 10 atau yang lebih lama) tidak mendukung $(...).
Stéphane Chazelas
@ StéphaneChazelas saya akan memasukkan ini.
Kusalananda
6

Ini berarti menjalankan apa yang ada di dalam tanda kurung dalam sebuah subkulit dan mengembalikannya sebagai nilai , dalam kasus Anda menugaskan itu varible.

marc
sumber