Содержимое файла в переменной 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