Я хочу прочитать файл и сохранить его в переменной, но мне нужно сохранить переменную, а не просто распечатать файл. Как я могу это сделать? Я написал этот скрипт, но это не совсем то, что мне было нужно:
#!/bin/sh
while read LINE
do
echo $LINE
done <$1
echo 11111-----------
echo $LINE
В моем сценарии я могу указать имя файла в качестве параметра, поэтому, если файл содержит, например, «aaaa», он выведет следующее:
aaaa
11111-----
Но это просто выводит файл на экран, и я хочу сохранить его в переменную! Есть простой способ сделать это?
cat
или$(<someFile)
приведет к неполному выходу (размер меньше , чем реальный файл).Ответы:
В кросс-платформенном наименьшем общем знаменателе
sh
вы используете:В
bash
илиzsh
, чтобы прочитать весь файл в переменную без вызоваcat
:Призывая
cat
вbash
илиzsh
чавкать файл будет считаться Бесполезный Использование Cat .Обратите внимание, что нет необходимости заключать в кавычки подстановку команд, чтобы сохранить переводы строки.
Смотрите: Bash Hacker's Wiki - Подстановка команд - Специальности .
источник
value="`cat config.txt`"
иvalue="$(<config.txt)"
безопаснее, если бы в файле config.txt были пробелы?cat
как указано выше, не всегда считается бесполезным использованиемcat
. Например,< invalid-file 2>/dev/null
приведет к сообщению об ошибке, которое не может быть перенаправлено/dev/null
, тогда какcat invalid-file 2>/dev/null
действительно перенаправлено на/dev/null
.value=$(<config.txt)
это хорошо, ноvalue = $(<config.txt)
плохо. Остерегайтесь этих мест.Если вы хотите прочитать весь файл в переменную:
Если вы хотите прочитать это построчно:
источник
echo "$value"
. В противном случае оболочка выполнит токенизацию пробела и расширение подстановочного знака для значения.read -r
вместо простоread
- всегда, если только вам не требуется странное унаследованное поведение, на которое вы намекаете.Две важные ловушки
которые были проигнорированы другими ответами до сих пор:
Удаление завершающего перевода строки из расширения команды
Это проблема для:
Тип решения, но не для
read
решений на основе.Расширение команды удаляет завершающие символы новой строки:
Выходы:
Это нарушает наивный метод чтения из файлов:
Обходной путь POSIX: добавьте дополнительный символ в расширение команды и удалите его позже:
Выходы:
Почти POSIX обходной путь: ASCII кодировать. См. ниже.
Удаление символов NUL
Не существует нормального способа Bash для хранения NUL-символов в переменных .
Это влияет как на расширение, так и на
read
решения, и я не знаю хорошего обходного пути для этого.Пример:
Выходы:
Ха, наш NUL ушел!
обходные:
ASCII кодировать. См. ниже.
используйте
$""
литералы расширения bash :Работает только для литералов, поэтому не полезно для чтения из файлов.
Обходной путь для ловушек
Сохраните версию файла в кодировке uuencode base64 в переменной и декодируйте перед каждым использованием:
Вывод:
uuencode и udecode - это POSIX 7, но не в Ubuntu 12.04 по умолчанию (
sharutils
пакет) ... Я не вижу альтернативы POSIX 7 для<()
расширения замены процесса bash, кроме записи в другой файл ...Конечно, это медленно и неудобно, поэтому я предполагаю, что реальный ответ таков: не используйте Bash, если входной файл может содержать символы NUL.
источник
S="$(printf "\\\'\"")"; echo $S
. Выход:\'"
. Так что это работает =)$()
расширением, мой пример показывает, что$()
расширение работает с\'"
.это работает для меня:
v=$(cat <file_path>) echo $v
источник
Как отмечает Сиро Сантилли, использование подстановок команд пропустит завершающие символы новой строки. Их обходной путь, заключающийся в добавлении завершающих символов, великолепен, но после его использования в течение некоторого времени я решил, что мне нужно решение, которое вообще не использует подстановку команд.
Мой подход теперь использует
read
вместе соprintf
встроенным-v
флагом для чтения содержимого стандартного ввода непосредственно в переменную.Это поддерживает входные данные с или без завершающих строк.
Пример использования:
источник
_contents="${_contents}${_line}\n "
сохранения новых строк?$'\n'
? Это необходимо, иначе вы добавляете литерал\
иn
символы. Ваш кодовый блок также имеет дополнительный пробел в конце, не уверен, что это преднамеренно, но в каждой последующей строке будет добавлен лишний пробел.Вы можете получить доступ к 1 строке за один раз для цикла
Скопируйте весь контент в файл (скажем, line.sh); казнить
источник
for
цикл не зацикливается на строках, он зацикливается на словах. В случае/etc/passwd
, случается, что каждая строка содержит только одно слово. Однако другие файлы могут содержать несколько слов в строке.