Искам да прочета файл и да го запиша в променлива, но трябва да запазя променливата, а не просто да изпиша файла. Как мога да направя това? Написах този скрипт, но той не е точно това, което ми трябваше:
#!/bin/sh
while read LINE
do
echo $LINE
done <$1
echo 11111-----------
echo $LINE
В моя скрипт мога да задам името на файла като параметър, така че, ако файлът съдържа "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
, за да се промъкне файл, ще се счита за Useless Use of Cat.
Обърнете внимание, че не е необходимо заместването на командата да се цитира, за да се запазят новите редове.
Вижте: Bash Hacker's Wiki - Command substitution - Specialities.
Два важни капана
които бяха пренебрегнати от другите отговори досега:
Премахване на последния нов ред от разширението на командата
Това е проблем за:
value="$(cat config.txt)"
но не и за решения, базирани на четене
.
Разширяването на командата премахва крайните нови редове:
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: добавете допълнителен символ към разширението на командата и го премахнете по-късно:
S="$(cat $FILE; printf a)"
S="${S%a}"
printf "$S" | od -tx1
Изходи:
0000000 61 0a 0a
0000003
Почти POSIX заобикаляне: ASCII кодиране. Вижте по-долу.
Отстраняване на символа NUL
Няма разумен начин в Bash за съхраняване на символи NUL в променливи.
Това засяга както решенията за разширяване, така и тези за четене
, и не знам добро решение за него.
Пример:
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 $""
:
S=$"a\0b"
printf "$S" | od -tx1
Работи само за литерали, така че не е полезно за четене от файлове.
Заобикаляне на клопките
Съхранявайте в променливата версия на файла, кодирана по 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
)... Не виждам алтернатива на POSIX 7 за разширението за заместване на процеса bash <()
, освен запис в друг файл...
Разбира се, това е бавно и неудобно, така че предполагам, че истинският отговор е: не'използвайте Bash, ако входният файл може да съдържа NUL символи.