Ответ 1
Неперехватывающие символы перевода строки не удаляются
Новые строки, которые вы ищете, есть, вы их просто не видите, потому что вы используете echo
без цитирования переменной.
Validation
$ a=$( df -H )
$ echo $a
Filesystem Size Used Avail Use% Mounted on /dev/sda3 276G 50G 213G 19% / udev 2.1G 4.1k 2.1G 1% /dev tmpfs 832M 820k 832M 1% /run none 5.3M 0 5.3M 0% /run/lock none 2.1G 320k 2.1G 1% /run/shm
$ echo "$a"
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 276G 50G 213G 19% /
udev 2.1G 4.1k 2.1G 1% /dev
tmpfs 832M 820k 832M 1% /run
none 5.3M 0 5.3M 0% /run/lock
none 2.1G 320k 2.1G 1% /run/shm
$
Удаляются новые символы новой строки
Как правильно указали @user4815162342, хотя новые строки на выходе не удаляются, завершающие новые строки удаляются с заменой команд. См. Эксперимент ниже:
$ a=$'test\n\n'
$ echo "$a"
test
$ b=$(echo "$a")
$ echo "$b"
test
$
В большинстве случаев это не имеет значения, потому что echo
добавит удаленную новую строку (если только она не вызывается с опцией -n
), но есть некоторые случаи кросс, в которых есть больше, чем одна завершающая строка новой строки на выходе программы, и они почему-то значительны.
Обходные
1. Добавить фиктивный символ
В этом случае, как указано @Scrutinizer, вы можете использовать следующее обходное решение:
$ a=$(printf 'test\n\n'; printf x); a=${a%x}
$ echo "$a"
test
$
Объяснение: Символ x
добавляется к выводу (используя printf x
) после строк новой строки. Поскольку новые строки больше не оканчиваются, они не удаляются подстановкой команд. Следующий шаг - удалить x
, который мы добавили, используя оператор %
в ${a%x}
. Теперь у нас есть исходный результат, со всеми новыми символами!
2. Чтение с использованием замены процесса
Вместо того, чтобы использовать подстановку команд для назначения вывода программы переменной, мы можем вместо этого использовать замещение процесса для подачи вывода программы к встроенной команде read
(кредит @ormaaj). Замена процесса сохраняет все новые строки. Чтение вывода в переменную несколько сложно, но вы можете сделать это следующим образом:
$ IFS= read -rd '' var < <( printf 'test\n\n' )
$ echo "$var"
test
$
Объяснение:
- Мы устанавливаем внутренний разделитель полей для команды чтения null, с
IFS=
. В противном случаеread
не назначил весь выводvar
, а только первый токен. - Мы вызываем
read
с параметрами-rd ''
.r
предназначен для предотвращения обратного слеша, чтобы действовать как специальный символ, а сd ''
установить разделитель на ничего, чтобы чтение читало весь вывод, а не только первую строку.
3. Чтение из трубы
Вместо того, чтобы использовать подстановку команд или процессов для назначения вывода программы переменной, мы можем вместо этого передать вывод программы команде read
(кредит @ormaaj). Трубопровод также сохраняет все новые строки. Обратите внимание, однако, что на этот раз мы устанавливаем необязательное поведение оболочки lastpipe
, используя shopt
встроенный. Это необходимо, так что команда read
выполняется в текущей среде оболочки. В противном случае переменная будет назначена в подоболочке, и она не будет доступна из остальной части script.
$ cat test.sh
#!/bin/bash
shopt -s lastpipe
printf "test\n\n" | IFS= read -rd '' var
echo "$var"
$ ./test.sh
test
$