Что означают скобки и знак $ в echo $ (ls)

Выходные данные

# ls

и

# echo $(ls)

одинаковы. Что именно означает знак $ и круглые скобки?

Кроме того, что происходит на техническом уровне, который приводит к тому, что вывод этих двух команд будет одинаковым?

7
задан 4 December 2011 в 06:12

4 ответа

() и $ () используются для запуска команд в подоболочке

Подробнее см. http://tldp.org/LDP/abs/html/subshells.html 112]

0
ответ дан 4 December 2011 в 06:12

Использование $ перед именем переменной вызывает значение, присвоенное переменной. Echo без $ будет просто выводить имя переменной на экран (или стандартное отображение).

0
ответ дан 4 December 2011 в 06:12

Это замена команды для bash.

Подстановка команды позволяет выводу команды заменить саму команду. Подстановка команд происходит, когда команда заключена следующим образом:

 $(command) or

 `command`

http://www.gnu.org/software/bash/manual/bashref.html#Command-Substitution

Подробнее:

http://tldp.org/LDP/abs/html/commandsub.html

http : //wiki.bash-hackers.org/syntax/expansion/cmdsubst

И хороший пример, похожий на ваш вопрос:

http://bashshell.net / Shell-скрипты / с помощью команды-замещение-в-Баш-оболочки-скрипта /

0
ответ дан 4 December 2011 в 06:12

Когда оболочка встречает текст, заключенный в $( ), она:

  1. Принимает ее как команду и (как bodhi.zazen говорит ) выполняет команда в подоболочке .
  2. Заменяет вывод команды вместо всего выражения (включая открывающее $( и закрывающее )).

Как объясняет ответ heartsmagic , это один из двух доступных синтаксисов для подстановки команд .

«Что ... приводит к тому, что выходные данные этих двух команд одинаковы?»

На самом деле несколько необычно, чтобы выходные данные ls были точно совпадает с выводом echo $(ls):

ek@Io:~/tmp$ ls
bar  foo
ek@Io:~/tmp$ echo $(ls)
bar foo

ls обычно разделяет имена файлов двумя или более пробелами или символом новой строки. Это помогает нам легче различать их, особенно потому, что пробелы в именах файлов встречаются довольно часто (но несколько последовательных пробелов встречаются реже).

Разделение слов

Когда я запустил echo $(ls), произошло следующее.

  1. Подстановка команд заменена $(ls) на:

    bar
    foo
    

    Вы можете быть удивлены, услышав это, так как это, вероятно, не то, что вы видите при запуске ls само собой! Это несоответствие в том, что выводит ls, объясняется ниже, но на самом деле это не причина, по которой вы в конечном итоге получаете один пробел между этими двумя словами. То же самое произошло бы, если бы $(ls) были заменены на bar foo (с двумя пробелами).

  2. После этого оболочка выполнила разбиение слов , обрабатывая bar и foo как отдельные аргументы для команды echo, а не как один аргумент, содержащий пространства.

Когда echo получает несколько аргументов (за исключением опций, таких как -n, которые обрабатываются специально и не печатаются вообще), он выводит их все, с одним пробелом между последующие аргументы. echo затем печатает новую строку (если не была передана опция -n).

Таким образом, echo $(ls) показывает вывод, подобный bar foo вместо bar foo.

Если вы запустите ls и в нем не будет ни одного файла, или только один файл, вывод ls будет часто совпадать с выводом echo $(ls). Даже в этом случае оно не всегда будет одинаковым, например, когда имя файла содержит пробелы, отличные от изолированных (одиночных) пробелов:

ek@Io:~/tmp2$ touch 'my   file'
ek@Io:~/tmp2$ ls
my   file
ek@Io:~/tmp2$ echo $(ls)
my file

Когда ls печатает несколько файлов, его вывод вряд ли будет точно так же, как на выходе из $(ls). Аналогично:

  • echo a b и echo $(echo a b) дают одинаковый выход, , но
  • echo 'a b' и echo $(echo 'a b') нет.

Это важно знать о подстановке команд - подстановки команд без кавычек могут быть разбиты на слова .

Обнаружение терминала

Если вы хотите предотвратить разбиение слов, вы можете заключить свое выражение для подстановки команд в двойные кавычки ("). Обычно этого достаточно, и, в частности, он будет работать с приведенными выше примерами на основе echo, а также с примером ls для каталога с одной записью, содержащей пробелы:

ek@Io:~/tmp2$ echo "$(ls)"
my   file

Однако, как как отмечалось выше, вы можете быть удивлены, обнаружив, что то, что вы видите при запуске ls, часто не то, что передается в echo вместо "$(ls)":

ek@Io:~/tmp$ ls
bar  foo
ek@Io:~/tmp$ echo "$(ls)"
bar
foo

Это потому, что ls ] проверяет, является ли стандартный вывод терминалом , чтобы решить, как форматировать его вывод , если форматирование вывода не указано явно.

  • Когда stdout является терминалом, ls выводит в вертикально отсортированных столбцах, как ls -C.
  • Когда stdout не является терминалом, ls перечисляет каждую запись в отдельной строке, как ls -1.

В подстановке команд стандартный вывод не является терминалом, потому что вывод команды не отправляется непосредственно на терминал, чтобы вы могли видеть - вместо этого он захватывается оболочкой и используется как часть другого команда.

Чтобы получить форматирование нескольких столбцов при запуске ls посредством подстановки команд, передайте ему флаг -C:

ek@Io:~/tmp$ echo "$(ls -C)"
bar  foo

(dir иногда предлагается в качестве альтернативы ls -C, и будет также работать для этого, хотя dir ведет себя как ls -C -b, а не просто ls -C .)

Shell Aliasing

Другая причина ls может иногда вести себя иначе, чем echo "$(ls)", это то, что ls может быть псевдонимом оболочки . Запустите alias ls, чтобы проверить; в Ubuntu вы обычно получаете alias ls='ls --color=auto', что означает, что когда ls появляется в качестве первого слова команды, которую вы выполняете в интерактивном режиме (и в некоторых, но не во всех других обстоятельствах), она заменяется на ls --color=auto.

Например, когда я запускаю ls, в нем перечислены каталоги, окрашенные в синий цвет, и исполняемые файлы, окрашенные в зеленый цвет (а также реализует много других правил окраски). --color=auto заставляет ls печатать цветной вывод, когда стандартный вывод является терминалом, а не иначе.

Чтобы получить цветной вывод при запуске ls посредством подстановки команд, передайте ему опцию --color или --color=always . Если хотите, вы можете объединить это с -C:

echo $(ls -C --color)

Обратите внимание, что хотя вы можете сделать ls псевдонимом для ls --color или ls --color=always вместо ls --color=auto и ls --color=always ] не волнует, является ли стандартный вывод терминалом ... этот псевдоним все равно не заставит ls производить цветной вывод при вызове подстановкой команды. Это связано с тем, что псевдонимы оболочки (в оболочках в стиле Борна , например bash ) раскрываются только тогда, когда оболочка видит их как первое слово команды (и они не наследуются подоболочками) .

0
ответ дан 4 December 2011 в 06:12

Другие вопросы по тегам:

Похожие вопросы: