Відповіді:
Завдання не видаляє символи нового рядка, це фактично робиться так echo. Для підтримки цих нових рядків потрібно просто поставити лапки навколо рядка:
echo "$testvar"
Це дасть бажаний результат. Дивіться наступну стенограму для демонстрації:
pax> cat num1.txt ; x=$(cat num1.txt)
line 1
line 2
pax> echo $x ; echo '===' ; echo "$x"
line 1 line 2
===
line 1
line 2
Причина , чому нові рядки замінюються пробіл не повністю робити з echoкомандою, а це поєднання речей.
Задавши командний рядок, bashрозбиває його на слова відповідно до документації для IFSзмінної:
IFS: роздільник внутрішнього поля, який використовується для розбиття слів після розширення ... значенням за замовчуванням є
<space><tab><newline>.
Це вказує, що за замовчуванням будь-який із цих трьох символів можна використовувати для розділення команди на окремі слова. Після цього розділювачі слів пропали, все, що у вас залишилося, - це список слів.
Поєднайте це з echoдокументацією ( bashвнутрішньою командою), і ви побачите, чому виводиться пробіли:
echo [-neE] [arg ...]: Виведіть аргументи, розділені пробілами, а потім новий рядок.
Коли ви використовуєте echo "$x", він змушує всю xзмінну бути одним словом відповідно bash, отже, вона не розділена. Це можна побачити за допомогою:
pax> function count {
...> echo $#
...> }
pax> count 1 2 3
3
pax> count a b c d
4
pax> count $x
4
pax> count "$x"
1
Тут countфункція просто виводить кількість наведених аргументів. 1 2 3І a b c dваріанти показати його в дії.
Потім ми спробуємо це з двома варіаціями на xзмінній. Один без лапок показують , що є чотири слова, "test", "1", "test"і "2". Додавання лапок робить це одним єдиним словом "test 1\ntest 2".
Це пов'язано із змінною IFS (Internal Field Separator), яка містить новий рядок.
$ cat xx1
1
2
$ A=`cat xx1`
$ echo $A
1 2
$ echo "|$IFS|"
|
|
Вирішення проблеми полягає в тому, щоб скинути IFS, щоб тимчасово не містити новий рядок :
$ IFSBAK=$IFS
$ IFS=" "
$ A=`cat xx1` # Can use $() as well
$ echo $A
1
2
$ IFS=$IFSBAK
ПОВЕРНУТИСЯ цієї жахливої зміни для IFS:
IFS=$IFSBAK
echo "$(IFS=''; cat text.txt)"
Bash -ge 4 має вбудований файл карти для читання рядків зі стандартного вводу в змінну масиву.
help mapfile
mapfile < file.txt lines
printf "%s" "${lines[@]}"
mapfile -t < file.txt lines # strip trailing newlines
printf "%s\n" "${lines[@]}"
Дивитися також:
http://bash-hackers.org/wiki/doku.php/commands/builtin/mapfile
Вашу змінну встановлено правильно testvar=$(cat test.txt). Щоб відобразити цю змінну, яка складається з нових символів рядка, просто додайте подвійні лапки, наприклад
echo "$testvar"
Ось повний приклад:
$ printf "test1\ntest2" > test.txt
$ testvar=$(<test.txt)
$ grep testvar <(set)
testvar=$'test1\ntest2'
$ echo "$testvar"
text1
text2
$ printf "%b" "$testvar"
text1
text2
envdirУтиліта надає простий спосіб зробити це. envdirвикористовує файли для представлення змінних середовища, з відображенням імен файлів для env var імен, а вміст файлів - зі значенням env var. Якщо вміст файлу містить нові рядки, так буде варіюватися і env var.
Дивіться https://pypi.python.org/pypi/envdir