Під час виконання цієї команди:
ls
термінал відображає вихід ls.
Під час виконання цієї команди:
echo $(ls)
оболонка фіксує вихід $(ls)і виконує розділення слів на ньому. За замовчуванням IFSце означає, що всі послідовності пробілу, включаючи символи нового рядка, замінені одним порожнім. Ось чому результат echo $(ls)з'являється в одному рядку.
Для розширеного обговорення розділення слів див . Поширені запитання Грега .
Придушення поділу слова
Оболонка не виконує розбиття слів на рядки в лапках. Таким чином, ви можете придушити поділ слів і зберегти багаторядковий вихід за допомогою:
echo "$(ls)"
ls і багаторядний вихід
Можливо, ви помітили, що lsіноді друкується більше одного файлу в рядку:
$ ls
file1 file2 file3 file4 file5 file6
Це за замовчуванням, коли вихід lsпереходить до терміналу. Коли вихід не збирається безпосередньо до терміналу, lsзмінює його за замовчуванням на один файл у рядку:
$ echo "$(ls)"
file1
file2
file3
file4
file5
file6
Така поведінка задокументована в man ls.
Ще одна тонкість: підміна команд і затримка нових рядків
$(...)- це підміна команд, і оболонка видаляє сліди нового рядка з виведення підстановки команд . Зазвичай це не помітно, оскільки за замовчуванням echoдо кінця виводу додається один новий рядок. Отже, якщо ви втратите один новий рядок з кінця $(...)і ви отримаєте його echo, зміни не буде. Якщо, однак, результат вашої команди закінчується двома або більше символами нового рядка, при цьому echoдодається лише один, у вашому результаті буде відсутні один або більше нових рядків. Як приклад, ми можемо використовувати printfдля генерування символів у новому рядку. Зауважте, що обидві наступні команди, незважаючи на різну кількість нових рядків, дають однаковий вихід одного порожнього рядка:
$ echo "$(printf "\n")"
$ echo "$(printf "\n\n\n\n\n")"
$
Така поведінка задокументована в man bash.
Ще один сюрприз: розширення імені шляху, вдвічі
Створимо три файли:
$ touch 'file?' file1 file2
Зверніть увагу на різницю між ls file?та echo $(ls file?):
$ ls file?
file? file1 file2
$ echo $(ls file?)
file? file1 file2 file1 file2
У випадку з echo $(ls file?)файлом глобус file?розширюється вдвічі , внаслідок чого імена файлів file1і file2двічі з’являються у висновку. Це тому, що, як зазначає Джеффікінс, розширення імені шляху здійснюється спочатку оболонкою перед lsзапуском, а потім ще раз, перш ніж echoзапускається.
Друге розширення шляху може бути припинено , якщо ми використовували подвійні лапки:
$ echo "$(ls file?)"
file?
file1
file2