Содержимое файла в переменной unix с символами новой строки

У меня есть текстовый файл test.txt со следующим содержимым:

text1
text2 

И я хочу присвоить содержимое файла переменной UNIX, но когда я это сделаю:

testvar=$(cat test.txt)
echo $testvar

результат:

text1 text2

вместо

text1
text2 

Может ли кто-нибудь предложить мне решение для этого?

Ответ 1

Назначение не удаляет символы новой строки, на самом деле это делает 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".

Ответ 2

Это связано с переменной IFS (Internal Field Separator), которая содержит новую строку.

$ cat xx1
1
2

$ A=`cat xx1`
$ echo $A
1 2

$ echo "|$IFS|"
|       
|

Обходной путь заключается в reset IFS, чтобы не содержать новую строку, временно:

$ IFSBAK=$IFS
$ IFS=" "
$ A=`cat xx1` # Can use $() as well
$ echo $A
1
2
$ IFS=$IFSBAK

Чтобы ИЗВЕСТИТЬ это ужасное изменение для IFS:

IFS=$IFSBAK

Ответ 3

Bash -ge 4 имеет встроенный mapfile для чтения строк из стандартного ввода в переменную массива.

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

Ответ 4

Ваша переменная правильно установлена ​​на 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

Ответ 5

Просто, если кто-то заинтересован в другом варианте:

content=( $(cat test.txt) )

a=0
while [ $a -le ${#content[@]} ]
do
        echo ${content[$a]}
        a=$[a+1]
done

Ответ 6

Утилита envdir предоставляет простой способ сделать это. envdir использует файлы для представления переменных среды, с сопоставлением имен файлов с именами env var и отображением содержимого файла в значения env var. Если содержимое файла содержит символы новой строки, то будет env var.

См. https://pypi.python.org/pypi/envdir