Яка різниця між $ (командою) і `командою` в програмуванні оболонок?


258

Щоб зберегти вихід команди як змінну в sh / ksh / bash, ви можете зробити будь-яке

var=$(command)

або

var=`command`

Яка різниця, якщо така є між двома методами?



Вкладене питання ви знайдете докладно в Посібнику з кодування Git: див. Мою відповідь нижче .
VonC

Відповіді:


274

Повернення / могили застаріли на користь $()заміни команд, тому що $()вони легко гніздяться всередині себе як у $(echo foo$(echo bar)). Існують і інші відмінності, такі як те, що підсумовуються кососуші риси у версії backtick / gravmark тощо.

Дивіться BashFAQ / 082 з кількох причин, щоб завжди віддати перевагу синтаксису $ (...).

Також дивіться специфікацію POSIX для отримання детальної інформації про різні відмінності.


25
Добре посилання, але текст не принизити зворотні лапки на користь $(...)- він просто відзначає їх в якості альтернативи.
Норман Грей

24
@NormanGray POSIX може не сказати слово застаріле, але він говорить, "the backquoted variety of command substitution is not recommended"що це лише давно звивистий спосіб сказати застаріле IMHO
SiegeX

11
POSIX не заставляє зворотних посилань, а скоріше додається $(...)як альтернативний метод. Невідома помилка реалізації із задніми посиланнями, але існує багато відомих помилок реалізації $(...) . Тому для проблем з переносністю рекомендується використовувати зворотні посилання для невкладених дзвінків. $(...)потрібен рекурсивний аналізатор, але це не було використано для ksh86, який запровадив цю функцію. Перевірте в in-ulm.de/~mascheck/various/cmd-subst список правильних реалізацій. Відповідна оболонка повинна підтримувати всі випадки, крім випадку D.2.
schily

2
У POSIX є інші речі, які потрібно розглядати як deprecated, наприклад, використання waitpid()цього заважає бачити цілі 32 біти від exit()параметра, але всі оболонки, окрім недавнього Bourne Shell, все ще використовують waitpid()замість waitid()виклику, який тепер доступний з 26 років.
schily

Посилання у відповіді натякає на наявність певних відмінностей між задніми таблицями та $(), що детальніше пояснено в цій частині документації . Відмінності полягають не лише в гніздування.
Якийсь програміст чувак

39

Вони поводяться так само. Різниця синтаксична: гніздо легше, $()ніж ``:

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

vs.

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

10
echo $(echo \$abc)не те саме, що echo `echo \$abc`‍- Відмінності існують $(echo \`)і для$(echo \\)
Пітер.O

Інша відмінність полягає в : echo foo `#comment`проти echo foo $(#comment). Другий не працює. (Використовується для коментування в багаторядковій команді.)
wisbucky

27

Липень 2014 року: команда f25f5e6 (автор: Elia Pinto ( devzero2000) , квітень 2014 року, Git 2.0) додає до вкладеного питання:

Форма, що котирується назад, є традиційним методом заміни команд і підтримується POSIX.
Однак усі, крім найпростіших видів використання, ускладнюються швидко.
Зокрема, вбудовані підстановки команд та / або використання подвійних лапок вимагають ретельного виходу із символом зворотної косої риски
.

Ось чому згадується git / Documentation / CodingGuidelines :

Ми віддаємо перевагу $( ... )заміні команд; на відміну від ``, він належним чином гніздиться .
Це повинно було бути так, як Борн написав це з першого дня, але, на жаль, це не так.

Тітон прокоментував :

Ось чому `echo `foo`` не працюватиме взагалі через притаманну неоднозначність, оскільки кожен ``може відкриватися чи закриватися.
Це може спрацювати в особливих випадках через удачу або особливі особливості.


Оновлення січня 2016 року: Git 2.8 (березень 2016 р.) Повністю позбавляється від підстав.

Див здійснювати ec1b763 , здійснювати 9c10377 , здійснюють c7b793a , здійснюють 80a6b3f , здійснюють 9375dcf , здійснюють e74ef60 , здійснюють 27fe43e , здійснюють 2525c51 , здійснюють becd67f , здійснюють a5c98ac , здійснюють 8c311f9 , здійснюють 57da049 , здійснюють 1d9e86f , здійснюють 78ba28d , здійснюють efa639f , здійснюють 1be2fa0 , зробити 38e9476 , здійснити 8823d2f , зробити 32858a0 , зробити cd914d8(12 січня 2016) Еліа Пінто ( devzero2000) .
(Об’єднав Хуніо С Хамано - gitster- в комісії e572fef , 22 січня 2016 р.)

Від Git 2.8 далі, це все $(...), не більше `...`.


2
$()також вказано POSIX - цитата, яка описує задні позиції як "підтримувані POSIX" таким чином, щоб зрозуміти, що це унікальне для них є оманливим. Це єдиний (епоха 1970-х років) пре-POSIX-Борн, де задні посилання є єдиним підтримуваним синтаксисом.
Чарльз Даффі

25

Коли використовується більш стара форма зворотного галочки, зворотна косою рисою зберігається буквальне значення, за винятком випадків, коли слідує $, `або \. Перша галочка, що не передує зворотній косої риси, завершує заміну команди.

При використанні нової $(command)форми всі символи між дужками складають команду; ніхто не лікується спеціально.

Обидві форми можуть бути вкладені, але для зворотного галочки потрібна наступна форма.

`echo \`foo\`` 

На відміну від:

$(echo $(foo))

1
Незначні виправлення, як версії backtick, так і $()версії сумісні з POSIX.
SiegeX

5

Різниця невелика, за винятком того, які символи без нагляду можна використовувати всередині команди. Ви навіть можете помістити команди `...` всередині $ (...) (і навпаки) для більш складної заміни двох рівнів.

Існує дещо інша інтерпретація символу / оператора зворотної косої риски. Серед іншого, коли вкладеності `...` команди заміни, ви повинні екранувати внутрішні ` символи з \, в той час як з $ () substition він розуміє вкладеності автоматично.


0

"Яка різниця, якщо така є між двома методами?"

Зверніть увагу на таку поведінку:

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

Ви отримаєте такі результати:

$A
A_VARIABLE

 

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.