Понимание обратной черты (`)

35

Я пробую команду

$ b=5; echo `$b`;
-bash: 5: command not found

но он не печатает 5, как это должно быть. Что мне здесь не хватает?

Что `(backquote / backtick) означает в командах? кажется, говорит, что `оценивает команды внутри и заменяет их выводом.

coolcric
источник
8
Обратите внимание, что обратные пометки не рекомендуются, поскольку вы потеряете возможность делать вложенные подстановки выполнения. Insetad, $ (somecommand) является предпочтительным. Имхо это улучшает читаемость.
Томми
6
@ Tommy, нет, обратные пометки могут быть вложенными, но это становится уходящим кошмаром, особенно при двойных кавычках.
Стефан Шазелас

Ответы:

52

Текст между обратными чертами выполняется и заменяется выводом команды (за исключением завершающих символов новой строки, и имейте в виду, что поведение оболочки меняется, когда в выводе присутствуют символы NUL). Это называется заменой команды, потому что она заменяется выводом команды. Поэтому, если вы хотите напечатать 5, вы не можете использовать обратные метки, вы можете использовать кавычки, например, echo "$b"или просто отбросить любую цитату и использовать echo $b.

Как вы можете видеть, поскольку $bсодержит 5, при использовании backticks bashпытается выполнить команду 5и, поскольку нет такой команды, он завершается с сообщением об ошибке.

Чтобы понять, как работают обратные пометки, попробуйте запустить это:

$ A=`cat /etc/passwd | head -n1`
$ echo "$A"

cat /etc/passwd |head -n1должен напечатать первую строку /etc/passwdфайла. Но так как мы используем обратные пометки, он не печатает это на консоли. Вместо этого он хранится в Aпеременной. Вы можете повторить $Aэто. Обратите внимание, что более эффективный способ печати первой строки - использование команды, head -n1 /etc/passwdно я хотел отметить, что выражение внутри обратных кавычек не должно быть простым.

Так что если первая строка в / etc / passwd root:x:0:0:root:/root:/bin/bash, первая команда будет динамически заменена на bash A="root:x:0:0:root:/root:/bin/bash".

Обратите внимание, что этот синтаксис имеет оболочку Bourne. Цитирование и экранирование быстро превращаются в кошмар, особенно когда вы начинаете их вкладывать. Ksh представил $(...)альтернативу, которая теперь стандартизирована ( POSIX ) и поддерживается всеми оболочками (даже оболочкой Bourne из Unix v9). Таким образом, вы должны использовать $(...)вместо этого в настоящее время, если вам не нужно быть переносимым на очень старые оболочки Борна.

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

Кшиштоф Адамски
источник
1
Привет @Krzysztof, это полезно! «поскольку $ b содержит 5, bash пытается запустить команду 5» - это именно то, что я искал
coolcric
you can use quotation marks, like echo "$b"=> "" делает что-нибудь особенное? Кажется, echo $bбудет работать так же хорошо.
Тутси Роллс
@ Анита: В общем, кавычки делают некоторые особые вещи (они изменяют способ обработки специальных символов - особенно пробелов), но в этом случае их можно удалить без особых проблем. Это связано с тем, что специальные символы не используются, и echoкоманда не заботится о количестве аргументов, которые она получает, поэтому, если bвнутри есть несколько пробелов, она получит несколько аргументов и все равно их напечатает. Это может быть не так для других команд (особенно когда переменная не установлена), поэтому я склонен всегда заключать переменные в кавычки.
Кшиштоф Адамски
было бы неплохо, если (POSIX)бы была ссылка на актуальный стандарт.
erikbwork
1
@ erikb85: Это примечание не было добавлено мной, но я отредактировал его по ссылке, как вы предложили :)
Кшиштоф Адамски
11

Обратный удар делает именно то, что вы говорите, он делает. Вы установили переменную в целое число. Когда вы помещаете эту переменную в обратные галочки, bash попытается выполнить ее как команду. Поскольку это не команда, вы получите ошибку, которую вы видели.

То, что вы хотите сделать, это просто:

$ b=5; echo $b

Чтобы лучше понять обратные трюки, сравните с:

$ b=5; a=`echo $b`; echo $a
  5
Тердон
источник
8

Идя шаг за шагом, ваша линия должна объяснить это.

$ b=5; echo `$b`;
  1. устанавливает переменную bна 5
  2. оценивает $b(эффективно работает 5)
  3. echoЕсли результат оценки выше.

Так что да, вы получите ожидаемый результат. Вы оцениваете содержимое переменной, а не фактическую команду, о которой думали. Все, что вы помещаете в обратные метки, просто оценивается (выполняется) в новой (под) оболочке.

gertvdijk
источник
привет @gertvdijk, спасибо за ваш пост! Я думал, что `возвращает все, что осталось после оценки его содержимого. Итак, я думал, что $ b вернул бы 5 для эха, чтобы напечатать его
coolcric