Я хочу прочитать файл и сохранить его в переменной, но мне нужно сохранить переменную, а не просто распечатать файл. Как я могу это сделать? Я написал этот script, но это не совсем то, что мне нужно:
#!/bin/sh
while read LINE
do
echo $LINE
done <$1
echo 11111-----------
echo $LINE
В моем script я могу указать имя файла в качестве параметра, поэтому, если файл содержит "aaaa", например, он распечатает это:
aaaa
11111-----
Но это просто печатает файл на экране, и я хочу сохранить его в переменной! Есть ли простой способ сделать это?
В кросс-платформенном, самом низком-общем знаменателе sh
вы используете:
#!/bin/sh
value=`cat config.txt`
echo "$value"
В bash
или zsh
, чтобы прочитать целый файл в переменной без вызова cat
:
#!/bin/bash
value=$(<config.txt)
echo "$value"
Вызов cat
в bash
или zsh
для удаления файла будет считаться Бесполезное использование Cat.
Обратите внимание, что нет необходимости процитировать замену команд для сохранения новых строк.
Если вы хотите прочитать весь файл в переменной:
#!/bin/bash
value=`cat sources.xml`
echo $value
Если вы хотите прочитать его по очереди:
while read line; do
echo $line
done < file.txt
Две важные ошибки
которые до сих пор игнорировались другими ответами:
Отключение новой строки от расширения команды
Это проблема для:
value="$(cat config.txt)"
но не для решений на основе read
.
Расширение команды удаляет завершающие символы новой строки:
S="$(printf "a\n")"
printf "$S" | od -tx1
Выходы:
0000000 61
0000001
Это нарушает наивный метод чтения из файлов:
FILE="$(mktemp)"
printf "a\n\n" > "$FILE"
S="$(<"$FILE")"
printf "$S" | od -tx1
rm "$FILE"
Обходное решение POSIX: добавьте дополнительный char к расширению команды и удалите его позже:
S="$(cat $FILE; printf a)"
S="${S%a}"
printf "$S" | od -tx1
Выходы:
0000000 61 0a 0a
0000003
Почти обходное решение POSIX: кодировка ASCII. См. Ниже.
Удаление символа NUL
Нет смысла использовать Bash способ хранения символов NUL в переменных.
Это влияет как на решения расширения, так и на read
, и я не знаю никаких хороших путей для этого.
Пример:
printf "a\0b" | od -tx1
S="$(printf "a\0b")"
printf "$S" | od -tx1
Выходы:
0000000 61 00 62
0000003
0000000 61 62
0000002
Ха, наш NUL ушел!
Обходные:
Кодирование ASCII. См. Ниже.
использовать Bash extension $""
литералы:
S=$"a\0b"
printf "$S" | od -tx1
Работает только для литералов, поэтому не полезно читать из файлов.
Обходной путь для подводных камней
Сохраните кодированную версию файла uuencode base64 в переменной и декодируйте перед каждым использованием:
FILE="$(mktemp)"
printf "a\0\n" > "$FILE"
S="$(uuencode -m "$FILE" /dev/stdout)"
uudecode -o /dev/stdout <(printf "$S") | od -tx1
rm "$FILE"
Вывод:
0000000 61 00 0a
0000003
uuencode и udecode POSIX 7, но не в Ubuntu 12.04 по умолчанию (sharutils
package)... Я не вижу Альтернатива POSIX 7 для процесса расширения Bash process <()
, кроме записи в другой файл...
Конечно, это медленно и неудобно, поэтому я предполагаю, что реальный ответ: не используйте Bash, если входной файл может содержать символы NUL.
cat
или$(<someFile)
-$(<someFile)
приведет к неполному выходу (размер меньше , чем реальный файл).