В чем разница между командами $(command) и `command` в программировании оболочки?

Чтобы сохранить вывод команды в качестве переменной в sh/ksh/bash, вы можете сделать либо

var=$(command)

или

var='command'

Какая разница между двумя методами?

Ответ 1

Backticks/gravemarks устарели в пользу $() для подстановки команд, потому что $() может легко встраиваться в себя, как в $(echo foo$(echo bar)). Существуют и другие различия, например, как обратная косая черта анализируется в версии backtick/gravemark и т.д.

См. BashFAQ/082 по нескольким причинам, которые всегда предпочитают синтаксис $ (...).

Также см. Спецификацию POSIX для получения подробной информации о различных различиях.

Ответ 2

Они ведут себя одинаково. Разница синтаксическая: легче вложить $(), чем ``:

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

против.

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

Ответ 3

Когда используется более ранняя форма обратного следа, обратная косая черта сохраняет свое буквальное значение, за исключением случаев, когда следуют $, `или or. Первый обратный тик, которому не предшествует обратная косая черта, завершает замену команды.

При использовании новой формы $(command) все символы между круглыми скобками составляют команду; ни один из них не рассматривается специально.

Обе формы могут быть вложенными, но для обратного тика требуется следующая форма.

`echo \`foo\`` 

В отличие от:

$(echo $(foo))

Ответ 4

Июль 2014: фиксация f25f5e6 (по Elia Pinto (devzero2000), апрель 2014 года, Git 2.0) добавляет к проблеме вложенности:

Форма обратной кавычки является традиционным методом подстановки команд и поддерживается POSIX.
Однако все, кроме самых простых, быстро усложняется.
В частности, встроенные подстановки команд и/или использование двойных кавычек требуют тщательного экранирования с символом обратной косой черты.

Вот почему git/Documentation/CodingGuidelines упоминает:

Мы предпочитаем $(... ) для подстановки команд; в отличие от '', он правильно гнездится.
Должно быть, это был способ, которым Борн написал это с первого дня, но, к сожалению, нет.

Титон прокомментировал:

Вот почему 'echo 'foo'' не будет работать вообще из-за присущего неопределенности, потому что каждый '' может быть открытие или закрытие.
Это может работать для особых случаев из-за удачи или особых функций.


Обновление в январе 2016 года: Git 2.8 (март 2016 года) полностью избавляется от backticks.

См. Commit ec1b763, commit 9c10377, commit c7b793a, commit 80a6b3f, commit 9375dcf, commit e74ef60, commit 27fe43e, commit 2525c51, commit becd67f, commit a5c98ac, commit 8c311f9, commit 57da049, commit 1d9e86f, commit 78ba28d, commit efa639f, commit 1be2fa0, commit 38e9476, совершить 8823d2f, совершить 32858a0, совершить cd914d8 (12 января 2016 года) Элиа Пинто (devzero2000).
(Слияние с Юнио С Хамано - gitster - в совершении e572fef, 22 января 2016 года)

Начиная с Git 2.8, все это $(...), не более '...'.

Ответ 5

Существует небольшая разница, за исключением того, что неэкранированные символы вы можете использовать внутри команды. Вы можете даже добавить команды `...` внутри $(...) (и наоборот) для более сложной замены двухуровневой команды.

Существует несколько другая интерпретация символа/оператора обратной косой черты. Помимо прочего, при вложенных командах подстановки `...` вы должны избегать внутренних символов ` с \,, тогда как $(), он автоматически распознает вложенность.

Ответ 6

"Какая разница между двумя методами?"

Обратите внимание на это поведение:

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

Вы получите следующие результаты:

$A
A_VARIABLE