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

210

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

var=$(command)

или

var='command'

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

  • 28
    Пожалуйста, смотрите BashFAQ / 082 .
  • 0
    Вложенная проблема подробно описана в Руководстве по кодированию Git: см. Мой ответ ниже .
Показать ещё 1 комментарий
Теги:
sh
ksh

6 ответов

244
Лучший ответ

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

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

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

  • 22
    Хорошая ссылка, но этот текст не заменяет кавычки в пользу $(...) - он просто отмечает их как альтернативы.
  • 22
    @NormanGray POSIX, возможно, не произносит слово « устарел», но он говорит: "the backquoted variety of command substitution is not recommended" что является просто длинным и скучным способом сказать, что ИМХО устарел.
Показать ещё 4 комментария
37

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

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

против.

listing=`ls -l \`cat filenames.txt\``
  • 10
    echo $(echo \$abc) - это не то же самое, что echo `echo \$abc`‍ Различия также существуют для $(echo \`) и $(echo \\)
25

Июль 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, все это $(...), не более '...'.

  • 3
    @VonC примечание к себе: это мой 150-й значок Некроманта.
  • 2
    $() также указывается POSIX - цитата, которая описывает обратные пометки как «поддерживаемые POSIX» таким образом, что подразумевает, что это уникально для них, вводит в заблуждение. Это только (эпоха 1970-х) pre-POSIX Bourne, где обратные помехи являются единственным поддерживаемым синтаксисом.
24

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

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

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

`echo \`foo\`` 

В отличие от:

$(echo $(foo))
  • 1
    Незначительная коррекция, версия backtick и версия $() соответствуют POSIX.
  • 0
    Отметил и обновил, спасибо.
5

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

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

0

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

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

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

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

$A
A_VARIABLE

Ещё вопросы

Сообщество Overcoder
Наверх
Меню