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


258

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

var=$(command)

или

var=`command`

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



Вы найдете вложенную проблему, подробно описанную в Руководстве по кодированию Git: см. Мой ответ ниже .
VonC

Ответы:


274

Обратные пометки / надписи были объявлены устаревшими в пользу $()подстановки команд, потому что они $()могут легко вкладываться в себя, как в $(echo foo$(echo bar)). Существуют и другие различия, такие как анализ обратной косой черты в версии backtick / gravemark и т. Д.

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

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


25
Хорошая ссылка, но этот текст не заменяет обратных кавычек в пользу $(...)- он просто отмечает их как альтернативы.
Норман Грей

24
@NormanGray POSIX, возможно, не произносит слово « устарел», но он говорит, "the backquoted variety of command substitution is not recommended"что это просто
слишком

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

2
В POSIX есть и другие вещи, которые нужно рассматривать как deprecated, например, использование waitpid()которых мешает вам видеть полные 32 бита из exit()параметра, но все оболочки, кроме недавней оболочки Bourne, все еще используют waitpid()вместо waitid()вызова, который теперь доступен, так как 26 лет
Шили

Ссылка в ответе намекает на наличие некоторых различий между обратными чертами и $(), что более подробно описано в этой части документации . Разница не только во вложении.
Какой-то программист чувак

39

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

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

против

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

10
echo $(echo \$abc)это не то же самое, что echo `echo \$abc`‍- Различия также существуют для $(echo \`)и $(echo \\)
Peter.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) .
(Объединено Junio ​​C Hamano - gitster- в коммите e572fef , 22 января 2016 г.)

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


2
$()также указывается POSIX - цитата, которая описывает обратные пометки как «поддерживаемые POSIX» таким образом, что подразумевает, что это уникально для них, вводит в заблуждение. Это только (эпоха 1970-х) pre-POSIX Bourne, где обратные помехи являются единственным поддерживаемым синтаксисом.
Чарльз Даффи

25

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

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

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

`echo \`foo\`` 

В отличие от:

$(echo $(foo))

1
Незначительная коррекция, версия backtick и $()версия соответствуют POSIX.
SiegeX

5

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

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


0

"Какая разница, если таковые имеются между двумя методами?"

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

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

Вы получите эти результаты:

$A
A_VARIABLE

 

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.