Apa perbedaan antara $ (perintah) dan `command` dalam pemrograman shell?


258

Untuk menyimpan output dari suatu perintah sebagai variabel di sh / ksh / bash, Anda bisa melakukan keduanya

var=$(command)

atau

var=`command`

Apa bedanya jika ada di antara kedua metode?



Anda akan menemukan masalah bersarang terinci dalam Pedoman Pengodean Git: lihat jawaban saya di bawah ini .
— VonC

Jawaban:


274

Backtick / gravemarks telah usang $()karena substitusi perintah karena $()dapat dengan mudah bersarang di dalam dirinya sendiri seperti pada $(echo foo$(echo bar)). Ada perbedaan lain seperti bagaimana backslash diuraikan dalam versi backtick / gravemark, dll.

Lihat BashFAQ / 082 untuk beberapa alasan untuk selalu lebih menyukai sintaks $ (...).

Lihat juga spesifikasi POSIX untuk informasi terperinci tentang berbagai perbedaan.


25
Link yang baik, tetapi bahwa teks tidak mencela backquotes mendukung $(...)- hanya mencatat mereka sebagai alternatif.
— Norman Gray

24
@NormanGray POSIX mungkin tidak mengatakan kata usang tetapi tidak mengatakan "the backquoted variety of command substitution is not recommended"yang hanya merupakan cara panjang untuk mengatakan IMHO usang
— SiegeX

11
POSIX tidak mencela backticks, melainkan ditambahkan $(...)sebagai metode alternatif. Tidak ada bug implementasi yang dikenal dengan backticks, tetapi ada banyak bug implementasi yang diketahui $(...) . Jadi untuk masalah portabilitas, disarankan untuk menggunakan backticks untuk panggilan yang tidak bersarang. $(...)membutuhkan parser rekursif tetapi ini tidak digunakan dengan ksh86 yang memperkenalkan fitur. Periksa in-ulm.de/~mascheck/various/cmd-subst untuk daftar implementasi yang benar. Shell yang menyesuaikan harus mendukung semua kasus kecuali kasus D.2.
— schily

2
Ada hal-hal lain dalam POSIX yang perlu dilihat deprecated, misalnya penggunaan waitpid()yang mencegah Anda melihat 32 bit penuh dari exit()parameter, tetapi semua shell kecuali Bourne Shell baru-baru ini masih menggunakan waitpid()alih-alih waitid()panggilan yang sekarang tersedia sejak 26 tahun.
— schily

Tautan dalam jawaban mengisyaratkan bahwa ada beberapa perbedaan antara backticks dan $(), yang lebih dijelaskan di bagian dokumentasi ini . Perbedaannya bukan hanya tentang bersarang.
— Beberapa programmer dude

39

Mereka berperilaku sama. Perbedaannya adalah sintaksis: lebih mudah untuk membuat sarang $()daripada ``:

listing=$(ls -l $(cat filenames.txt))

vs.

listing=`ls -l \`cat filenames.txt\``

10
echo $(echo \$abc)tidak sama dengan echo `echo \$abc`‍- Perbedaan juga ada untuk $(echo \`)dan $(echo \\)
— Peter.O

Perbedaan lain adalah: echo foo `#comment`vs echo foo $(#comment). Yang kedua tidak berhasil. (Digunakan untuk berkomentar dalam perintah multi-line.)
— wisbucky

27

Juli 2014: Komit f25f5e6 (oleh Elia Pinto ( devzero2000) , April 2014, Git 2.0) menambah masalah bersarang:

Bentuk backquoted adalah metode tradisional untuk substitusi perintah, dan didukung oleh POSIX.
Namun, semua kecuali penggunaan paling sederhana menjadi rumit dengan cepat.
Khususnya, penggantian perintah yang disematkan dan / atau penggunaan tanda kutip ganda memerlukan pelarian yang hati-hati dengan karakter backslash
.

Itulah mengapa git / Documentation / CodingGuidelines menyebutkan:

Kami lebih suka $( ... )substitusi komando; tidak seperti ``, itu benar sarang .
Seharusnya itu cara Bourne mengejanya sejak hari pertama, tapi sayangnya tidak.

thiton berkomentar :

Itu sebabnya `echo `foo`` tidak akan bekerja secara umum karena ambiguitas yang melekat karena masing ``- masing dapat membuka atau menutup.
Mungkin berfungsi untuk kasus khusus karena keberuntungan atau fitur khusus.


Pembaruan Januari 2016: Git 2.8 (Maret 2016) sepenuhnya menghilangkan backticks.

Lihat komit ec1b763 , komit 9c10377 , komit c7b793a , komit 80a6b3f , komit 9375dcf , komit e74ef60 , komit 27fe43e , komit 2525c51 , komit becd67f , komit a5c98ac , komit 8c311f9 , komit 57da049 , komit 1d9e86f , komit 78ba28d , komit efa639f , komit 1be2fa0 , komit 38e9476 , komit 8823d2f , komit 32858a0 , komit cd914d8(12 Jan 2016) oleh Elia Pinto ( devzero2000) .
(Digabung oleh Junio ​​C Hamano - gitster- di commit e572fef , 22 Jan 2016)

Dari Git 2.8 dan seterusnya, itu semua $(...), tidak ada lagi `...`.


2
$()juga ditentukan POSIX - kutipan yang menggambarkan backticks sebagai "didukung POSIX" sedemikian rupa sehingga menyiratkan bahwa ini unik bagi mereka menyesatkan. Ini hanya (era 1970-an) pra-POSIX Bourne di mana backticks adalah satu-satunya sintaks yang didukung.
— Charles Duffy

25

Ketika bentuk centang-kembali yang lebih lama digunakan, backslash mempertahankan makna literalnya kecuali ketika diikuti oleh $, `, atau \. Centang-balik pertama yang tidak diawali dengan backslash mengakhiri substitusi perintah.

Saat menggunakan $(command)formulir yang lebih baru , semua karakter di antara tanda kurung membuat perintah; tidak ada yang diperlakukan secara khusus.

Kedua formulir dapat bersarang, tetapi variasi tanda centang kembali memerlukan formulir berikut.

`echo \`foo\`` 

Sebagai lawan:

$(echo $(foo))

1
Koreksi kecil, baik versi backtick dan $()versi yang sesuai dengan POSIX.
— SiegeX

5

Ada sedikit perbedaan, kecuali untuk karakter yang tidak terhindar yang dapat Anda gunakan di dalam perintah. Anda bahkan dapat memasukkan perintah `...` di dalam perintah $ (...) (dan sebaliknya) untuk substitusi perintah dua tingkat yang lebih rumit.

Ada interpretasi yang sedikit berbeda dari karakter / operator backslash. Antara lain, ketika bersarang `...` perintah substitusi, Anda harus melarikan diri ` karakter dalam dengan \, sedangkan dengan substitusi $ () ia memahami sarang secara otomatis.


0

"Apa bedanya jika ada di antara kedua metode itu?"

Perhatikan perilaku ini:

A="A_VARIABLE"
echo "$(echo "\$A")"
echo "`echo "\$A"`"

Anda akan mendapatkan hasil ini:

$A
A_VARIABLE

 

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.