Выход
# ls
и
# echo $(ls)
одинаковый. Что означает знак $ и скобка?
Кроме того, что происходит на техническом уровне, который приводит к тому, что вывод этих двух команд будет таким же?
Это подстановка команды для 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
Когда оболочка встречает текст, заключенный в $( ), он:
принимает его за команду и (как говорит 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') этого не делают.Это важная вещь, которую нужно знать о подстановке команд - некотируемые подстановки команд подлежат разбиению слов.
Если вы хотите предотвратить слово расщепление, вы можете заключить выражение для подстановки команды в двойные кавычки ("). Обычно это достаточно и, в частности, будет работать с приведенными выше примерами 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.)
Другая причина [ 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) расширяются только тогда, когда оболочка видит их в качестве первого слова команды (и они не унаследованы подоболочки).
() и $ () используются для запуска команд в подоболочке
Подробнее см. http://tldp.org/LDP/abs/html/subshells.html
Использование $ перед именем переменной вызывает значение, присвоенное переменной. Echo без $ будет просто печатать имя переменной на экране (или стандартном выходе).