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.