Jaka jest różnica między $ (polecenie) a `polecenie` w programowaniu powłoki?


258

Aby zapisać wynik polecenia jako zmienną w sh / ksh / bash, możesz zrobić jedno z nich

var=$(command)

lub

var=`command`

Jaka jest różnica między tymi dwiema metodami?


29
Proszę zobaczyć BashFAQ / 082 .
— Wstrzymano do odwołania.

Zagnieżdżony problem znajdziesz szczegółowo w wytycznych Git Coding Guideline: patrz moja odpowiedź poniżej .
— VonC,

Odpowiedzi:


274

Znaki wsteczne / znaki grawitacyjne zostały wycofane na korzyść $()zastępowania poleceń, ponieważ $()mogą łatwo zagnieżdżać się w sobie jak w $(echo foo$(echo bar)). Istnieją inne różnice, takie jak sposób analizowania ukośników odwrotnych w wersji backtick / gravemark itp.

Zobacz BashFAQ / 082 z kilku powodów, aby zawsze preferować składnię $ (...).

Zobacz także specyfikację POSIX, aby uzyskać szczegółowe informacje na temat różnych różnic.


25
Dobre połączenie, ale tekst nie potępiać odwrotnego cudzysłowiu rzecz $(...)- po prostu zauważa je jako alternatywy.
— Norman Gray

24
@NormanGray POSIX może nie powiedzieć słowa przestarzałe, ale mówi, "the backquoted variety of command substitution is not recommended"co jest po prostu
— odrętwiałym

11
POSIX nie przestarzał backticks, ale raczej dodano $(...)jako alternatywną metodę. Nie ma znanego błędu implementacji z backtickami, ale istnieje wiele znanych błędów implementacji z $(...) . Dlatego w przypadku problemów związanych z przenośnością zaleca się stosowanie tylnych zwrotów w przypadku zagnieżdżonych połączeń. $(...)wymaga parsera rekurencyjnego, ale nie został on użyty w ksh86, który wprowadził tę funkcję. Sprawdź inulm.de/~mascheck/various/cmd-subst, aby uzyskać listę poprawnych implementacji. Powłoka zgodna musi obsługiwać wszystkie przypadki z wyjątkiem sprawy D.2.
— schily

2
W POSIX są inne rzeczy, które należy postrzegać jako deprecated, np. Użycie waitpid()tego uniemożliwia dostrzeżenie pełnych 32 bitów z exit()parametru, ale wszystkie powłoki z wyjątkiem ostatniej powłoki Bourne'a nadal używają waitpid()zamiast waitid()wywołania, które jest teraz dostępne od 26 lat
— schily

Link w odpowiedzi wskazuje, że istnieją pewne różnice między backtickami i $()co jest bardziej wyjaśnione w tej części dokumentacji . Różnice dotyczą nie tylko zagnieżdżenia.
— Jakiś programista koleś

39

Zachowują się tak samo. Różnica jest składniowa: łatwiej jest zagnieździć $()niż ``:

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

vs.

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

10
echo $(echo \$abc)to nie to samo, co echo `echo \$abc`‍- Różnice istnieją również dla $(echo \`)i $(echo \\)
— Peter.O

Inną różnicą jest to: echo foo `#comment`vs echo foo $(#comment). Drugi nie działa. (Używane do komentowania w poleceniu wieloliniowym.)
— wisbucky,

27

Lipiec 2014: Zatwierdzenie f25f5e6 (autor: Elia Pinto ( devzero2000) , kwiecień 2014, Git 2.0) dodaje do problemu zagnieżdżania:

Postać w cudzysłowie jest tradycyjną metodą zastępowania poleceń i jest obsługiwana przez POSIX.
Jednak wszystkie zastosowania oprócz najprostszych szybko się komplikują.
W szczególności wbudowane podstawienia poleceń i / lub stosowanie podwójnych cudzysłowów wymagają ostrożnego ucieczki ze znakiem odwrotnego ukośnika
.

Właśnie dlatego git / Documentation / CodingGuidelines wspomina:

Preferujemy $( ... )zastępowanie poleceń; w przeciwieństwie do ``, poprawnie się zagnieżdża .
Powinno tak wyglądać Bourne od pierwszego dnia, ale niestety tak nie jest.

Thiton skomentował :

To dlatego `echo `foo`` nie działa w ogóle z powodu wewnętrznej dwuznaczności, ponieważ każda z nich ``może się otwierać lub zamykać.
Może to działać w szczególnych przypadkach z powodu szczęścia lub specjalnych funkcji.


Aktualizacja styczeń 2016: Git 2.8 (marzec 2016) całkowicie pozbywa się backticksa.

Zobacz popełnić ec1b763 , popełnić 9c10377 , popełnić c7b793a , popełnić 80a6b3f , popełnić 9375dcf , popełnić e74ef60 , popełnić 27fe43e , popełnić 2525c51 , popełnić becd67f , popełnić a5c98ac , popełnić 8c311f9 , popełnić 57da049 , popełnić 1d9e86f , popełnić 78ba28d , popełnić efa639f , popełnić 1be2fa0 , zobowiązać 38e9476 , zatwierdzenie 8823d2f , zatwierdzenie 32858a0 , zatwierdzenie cd914d8(12 stycznia 2016) autor: Elia Pinto ( devzero2000) .
(Połączone przez Junio ​​C Hamano - gitster- w commit e572fef , 22 stycznia 2016)

Począwszy od Gita 2.8, to już wszystko $(...), nic więcej `...`.


2
$()jest również określony przez POSIX - cytat opisujący backtyki jako „wspierane przez POSIX” w taki sposób, aby sugerować, że jest to dla nich unikalne, jest mylący. Jest to jedyna (era 1970) wersja sprzed POSIX Bourne, gdzie jedyną obsługiwaną składnią są backtyki.
— Charles Duffy

25

Gdy używana jest starsza forma tykania, odwrotny ukośnik zachowuje swoje dosłowne znaczenie, chyba że po nim następuje $, `lub \. Pierwszy tyknięcie poprzedzone odwrotnym ukośnikiem kończy podstawianie poleceń.

Podczas korzystania z nowszej $(command)formy wszystkie znaki między nawiasami tworzą polecenie; żaden nie jest traktowany specjalnie.

Obie formy można zagnieżdżać, ale odmiana zaznaczania wstecznego wymaga następującej formy.

`echo \`foo\`` 

W przeciwieństwie do:

$(echo $(foo))

1
Niewielka korekta, zarówno wersja wsteczna, jak i $()wersja są zgodne z POSIX.
— SiegeX

5

Różnica jest niewielka, z wyjątkiem tego, jakich nieskalowanych znaków możesz użyć wewnątrz polecenia. Możesz nawet umieścić polecenia „...” wewnątrz poleceń $ (...) (i odwrotnie), aby uzyskać bardziej skomplikowane podstawianie poleceń na dwóch poziomach.

Istnieje nieco inna interpretacja znaku / operatora odwrotnego ukośnika. Między innymi, zagnieżdżając polecenia podstawienia `...` , musisz uciec wewnętrznymi znakami `za pomocą \, podczas gdy w przypadku podstacji $ () automatycznie rozpoznaje zagnieżdżanie.


0

„Jaka jest różnica między tymi dwiema metodami?”

Zwróć uwagę na to zachowanie:

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

Otrzymasz te wyniki:

$A
A_VARIABLE

 

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.