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

Выход

# ls

и

# echo $(ls)

одинаковый. Что означает знак $ и скобка?

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

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

4 ответа

Это подстановка команды для bash.

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

 `command`

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

[d5 ] Подробнее:

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

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

И хороший пример, аналогичный вашему вопросу:

http: //wiki.bash-hackers. орг / синтаксис / расширения / cmdsubst

6
ответ дан 25 May 2018 в 16:16

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

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

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

«Что ... заставляет вывод этих двух команд быть одинаковыми?»

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

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

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

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

Когда я побежал echo $(ls) произошло следующее:

Заставляет его быть командой и (как говорит bodhi.zazen) запускает команду в подоболочке. Затем оболочка выполнила разбиение слов, рассматривая 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') этого не делают.

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

Terminal Detection

Если вы хотите предотвратить слово расщепление, вы можете заключить выражение для подстановки команды в двойные кавычки ("). Обычно это достаточно и, в частности, будет работать с приведенными выше примерами 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 проверяет, является ли echo терминалом один из двух доступных синтаксисов , когда форматирование вывода явно не указано.

[ f36] и echo $(echo a b) выдают одинаковый вывод, но Когда 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

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

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

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

echo $(ls -C --color)

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

2
ответ дан 25 May 2018 в 16:16

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

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

1
ответ дан 25 May 2018 в 16:16

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

0
ответ дан 25 May 2018 в 16:16

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

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