Новий рядок у bash змінних


9

Я намагаюся зберігати кілька рядків у змінній bash, але, схоже, це не працює.

Наприклад, якщо я перелічу /binодин файл на рядок і зберігаю його $LS, то я передаю $LSяк stdin до wc, він завжди повертає 1:

$ ls -1 /bin | wc -l
134
$ LS=$(ls -1 /bin); wc -l <<< $LS
1

Якщо я спробую вивести на екран, я отримую різні результати: echoдрукує всі рядки в одному рядку, а printfдрукує лише перший рядок:

#!/bin/bash
LS=$(ls -1 /bin)
echo $LS
printf $LS

Отже, змінна bash може містити кілька рядків?

Відповіді:


15

Вам потрібно подвоїти його цитування (і в більшості випадків ви повинні подвоїти змінні котирування ):

echo "$LS"

Але не використовуйте ехо для друку вмісту змінних, використовуючи замість цього printf :

printf '%s\n' "$LS"

1
Просто для кращої точки щодо загальної відповіді: printf очікує, що рядок формату буде його першим параметром, тому вони не бачили того, що очікували. Якщо вони хочуть бачити нові рядки у висновку з printf, арбітражно розбившись на пробіли, printf "%s\n" $LSце зробить це.
Jeff Schaller

% LS має бути $ LS, btw (я не зміг зробити таке коротке редагування)
Jeff Schaller

Дякую! Звичайно, це працює і з wcіншими командами:wc -l <<< "$LS"
Wizard79

1
@JeffSchaller: Ні, у цьому випадку ви не повинні цитувати змінну, просто використовуючи, printf '%s\n' "$LS"якщо ви хочете переглянути новий рядок. Це неправильне введення тексту, виправлено!
cuonglm

Чому не слід використовувати ехо для друку змінних?
123

9

Нові рядки знаходяться у змінній. LS=$(ls -1)встановлює змінну LSна вихід ls -1(що дає такий же вихід, як і ls, до речі, за винятком випадків, коли вихід надходить до терміналу), мінус кінцеві нові рядки.

Проблема полягає в тому, що ви видаляєте нові рядки, коли ви роздруковуєте значення. У сценарії оболонки $LSне означає "значення змінної LS", це означає "взяти значення LS, розділити його на слова відповідно до IFSта інтерпретувати кожне слово як глобальний зразок". Щоб отримати значення LS, вам потрібно написати "$LS"або загалом поставити $LSміж подвійними лапками.

echo "$LS"друкує значення LS, за винятком деяких оболонок, які інтерпретують символи зворотної косої риси, за винятком кількох значень, які починаються з -.

printf "$LS"друкує значення до LSтих пір, поки воно не містить жодного відсотка або зворотнього косого символу і (при більшості реалізацій) не починається з -.

Щоб LSточно надрукувати значення , використовуйте printf %s "$LS". Якщо ви хочете новий рядок наприкінці, використовуйте printf '%s\n' "$LS".

Зауважте, що $(ls)це загалом не список файлів у поточному каталозі. Це працює лише тоді, коли у вас є достатньо приручені імена файлів. Щоб отримати список імен файлів (крім точкових файлів), необхідно використовувати підстановочні: *. Результат - це список рядків, а не рядок, тому ви не можете призначити його рядкової змінної; ви можете використовувати змінну масиву files=(*)в оболонках, які їх підтримують (ksh93, bash, zsh).

Для отримання додаткової інформації див. Чому мій скрипт оболонки задавлюється пробілом або іншими спеціальними символами?


printf "$ LS" також піддасться розбору символів зворотної косої риси, подібно до echo
cnst

0

Вищезгадане

printf '%s\n' "$LS"

- єдине правильне рішення.

Дозвольте мені продемонструвати, що інші запропоновані рішення, як echoі printf, так і просто не працюють належним чином:

$ mkdir t
$ cd t
$ touch \\n
$ LS=$(ls -l)
$ echo "$LS"
total 0
-rw-r--r--  1 domain  domain  0 Nov  5 06:12

$ printf "$LS\n"
total 0
-rw-r--r--  1 domain  domain  0 Nov  5 06:12

$ printf '%s\n' "$LS"
total 0
-rw-r--r--  1 domain  domain  0 Nov  5 06:12 \n
$ ls -l
total 0
-rw-r--r--  1 domain  domain  0 Nov  5 06:12 \n
$ rm \\n
$ cd ..
$ rmdir t
$

(Можна також протестувати V=$(printf 'line0:\\n\\n\nline1.\n') printf '%s\n' "$V"і з варіаціями.)

Тоді як \nу назви файлів можуть бути не настільки поширеними, збережіть git diffзмінну, і ваші шанси зустрітися з буквальним словом \nрізко зростуть.


Зауважте, що kshі zshтакож підтримує, print -r -- "$LS"і zshє echo -E - $LS. cshмає , echo $LS:qоднак , що не виводить символ нового рядка , якщо $ LS порожня, і отримати многострочное значення в $ LS в першу чергу , це досить складно в CSH.
Стефан Шазелас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.