Kabuk programlamasında $ (command) ve `command` arasındaki fark nedir?


258

Bir komutun çıktısını sh / ksh / bash içinde değişken olarak saklamak için,

var=$(command)

veya

var=`command`

İki yöntem arasındaki fark nedir?



Yuvalanmış sorunu Git Kodlama Kılavuzu'nda ayrıntılı olarak bulacaksınız: cevabımı aşağıya bakın .
— VonC

Yanıtlar:


274

Geri dönüşler / gravemarklar, $()komut değiştirme yerine lehine reddedilmiştir, çünkü $()kendi içinde olduğu gibi kolayca kendi içinde yuva yapabilirler $(echo foo$(echo bar)). Ters eğik çizgi / gravemark sürümünde ters eğik çizgilerin nasıl ayrıştırıldığı gibi başka farklılıklar da vardır.

Her zaman $ (...) sözdizimini tercih etmek için birkaç nedenden dolayı BashFAQ / 082'ye bakın .

Ayrıca , çeşitli farklılıklar hakkında ayrıntılı bilgi için POSIX spesifikasyonuna bakın .


25
İyi bağlantı, fakat metin değil bu kullanımdan kaldırmak lehine backquotes $(...)- sadece alternatif olarak onları belirtiyor.
— Norman Gray

24
@NormanGray POSIX, kullanımdan kaldırılmış kelimesini söylemeyebilir, ancak "the backquoted variety of command substitution is not recommended"IMHO
— SiegeX'in 16:15

11
POSIX geri çekilmeyi reddetti, daha ziyade $(...)alternatif bir yöntem olarak eklendi . Backticks ile bilinen bir uygulama hatası yoktur, ancak bilinen birçok uygulama hatası vardır $(...) . Bu nedenle, taşınabilirlik sorunları için iç içe olmayan çağrılar için ters vuruş kullanılması önerilir. $(...)özyinelemeli ayrıştırıcıya ihtiyaç duyar, ancak bu özelliği tanıtan ksh86 ile kullanılmaz. Doğru uygulamaların bir listesi için in-ulm.de/~mascheck/various/cmd-subst adresini kontrol edin . Uygun bir kabuk D.2 durumu hariç tüm durumları desteklemelidir.
— schily

2
POSIX'te görülmesi gereken başka şeyler de var deprecated, örneğin waitpid(), exit()parametrenin tüm 32 bitini görmenizi engelleyen kullanımı , ancak son Bourne Kabuğu dışındaki tüm mermiler , şu anda mevcut waitpid()olan waitid()çağrı yerine hala kullanıyor 26 yıl.
— schily

Yanıttaki bağlantı, ters çentikler arasında ve belgelerin bu bölümünde$() daha fazla açıklanmış olan bazı farklılıklar olduğunu ima eder . Farklılıklar sadece yuvalama ile ilgili değildir.
— Bazı programcı ahbap

39

Aynı davranıyorlar. Fark sözdizimseldir: yuvalamak $()daha kolay ``:

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

vs.

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

10
echo $(echo \$abc)ile aynı değildir echo `echo \$abc`‍- $(echo \`)ve için de farklılıklar vardır ve $(echo \\)
— Peter.O

Diğer bir fark ise: echo foo `#comment`v echo foo $(#comment). İkincisi çalışmıyor. (Çok satırlı bir komutta yorum yapmak için kullanılır.)
— wisbucky

27

Temmuz 2014: f25f5e6 taahhüdü ( Elia Pinto ( devzero2000) , Nisan 2014, Git 2.0) yuvalama sorununa katkıda bulunur:

Geri sıralanan form, komut değiştirme için geleneksel yöntemdir ve POSIX tarafından desteklenir.
Bununla birlikte, en basit kullanımlar hariç tümü hızlı bir şekilde karmaşık hale gelir.
Özellikle, gömülü komut ikameleri ve / veya çift tırnak kullanımı ters eğik çizgi karakteriyle dikkatlice kaçmayı gerektirir
.

Bu nedenle git / Documentation / CodingGuidelines şunları belirtir :

$( ... )Komut yerine koymayı tercih ediyoruz ; `` aksine, düzgün bir şekilde yuva yapar .
Bourne'un ilk günden itibaren hecelemesi gerekiyordu, ama maalesef öyle değil.

thiton yorumladı :

Bu nedenle `echo `foo`` içsel belirsizlik nedeniyle genel olarak çalışmaz, çünkü her biri ``açılıp kapanabilir.
Şans veya özel özellikler nedeniyle özel durumlar için işe yarayabilir.


Ocak 2016 Güncellemesi: Git 2.8 (Mart 2016) ters çentiklerden tamamen kurtuldu.

Bkz ec1b763 işlemek , 9c10377 taahhüt , c7b793a işlemek , 80a6b3f işlemek , 9375dcf taahhüt , e74ef60 taahhüt , 27fe43e taahhüt , 2525c51 taahhüt , becd67f taahhüt , a5c98ac işlemek , 8c311f9 taahhüt , 57da049 taahhüt , 1d9e86f işlemek , 78ba28d taahhüt , efa639f işlemek , 1be2fa0 işlemek , işlemek 38e9476 , taahhüt 8823d2f , taahhüt 32858a0 , taahhüt cd914d8(12 Oca 2016) Elia Pinto ( devzero2000) tarafından yapılmıştır .
(Göre Birleştirilmiş - Junio Cı Hamano gitster- içinde e572fef tamamlama 2016 Ocak 22)

Git 2.8'den itibaren, hepsi $(...)artık `...`.


2
$()POSIX tarafından da belirtilir - backticks'i "POSIX destekli" olarak tanımlayan bir teklif, bunun kendilerine özgü olduğunu ima edecek şekilde yanıltıcıdır. Sadece (1970'lerde) POSIX öncesi Bourne, desteklenen tek sözdizimidir.
— Charles Duffy

25

Daha eski geri tıklatma formu kullanıldığında, ters eğik çizgi, $, `veya \ ile başlayanlar dışında gerçek anlamını korur. Bir ters eğik çizgiden önce gelmeyen ilk geri işaret komut yerine koymayı sonlandırır.

Yeni $(command)formu kullanırken, parantezler arasındaki tüm karakterler komutu oluşturur; hiçbirine özel muamele edilmez.

Her iki form da iç içe yerleştirilebilir, ancak arka onay çeşidi aşağıdaki formu gerektirir.

`echo \`foo\`` 

Aksine:

$(echo $(foo))

1
Küçük düzeltme, hem backtick sürümü hem de $()sürüm POSIX uyumludur.
— SiegeX

5

Komutun içinde kaçan karakterleri kullanabileceğiniz dışında çok az fark vardır. Daha karmaşık iki seviyeli derin bir komut ikamesi için `... ' komutlarını $ (...) olanların içine (ve tersi) bile koyabilirsiniz .

Ters eğik çizgi karakterinin / operatörün biraz farklı bir yorumu vardır. Diğer şeylerin yanı sıra, `...` ikame komutlarını iç içe yerleştirirken , iç ` karakterlerden \ ile kaçmanız gerekirken, $ () alt bölümü ile iç içe yerleştirmeyi otomatik olarak anlar.


0

"İki yöntem arasındaki fark nedir?"

Bu davranışa dikkat edin:

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

Bu sonuçları alacaksınız:

$A
A_VARIABLE

 

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.