Voglio leggere un file e salvarlo in una variabile, ma ho bisogno di mantenere la variabile e non solo stampare il file. Come posso farlo? Ho scritto questo script ma non è proprio quello di cui avevo bisogno:
#!/bin/sh
while read LINE
do
echo $LINE
done <$1
echo 11111-----------
echo $LINE
Nel mio script, posso dare il nome del file come parametro, quindi, se il file contiene "aaaa", per esempio, stamperebbe questo:
aaaa
11111-----
Ma questo stampa solo il file sullo schermo, e io voglio salvarlo in una variabile! C'è un modo semplice per farlo?
In multipiattaforma, il minimo comune denominatore sh
si usa:
#!/bin/sh
value=`cat config.txt`
echo "$value"
In bash
o zsh
, per leggere un intero file in una variabile senza invocare cat
:
#!/bin/bash
value=$(<config.txt)
echo "$value"
Invocare cat
in bash
o zsh
per leggere un file sarebbe considerato un Useless Use of Cat.
Si noti che non è necessario citare la sostituzione del comando per preservare le newline.
Vedere: Bash Hacker's Wiki - Sostituzione dei comandi - Specialità.
Due importanti insidie
che sono state ignorate dalle altre risposte finora:
Rimozione del newline in coda all'espansione del comando
Questo è un problema per il:
value="$(cat config.txt)"
ma non per le soluzioni basate sulla lettura.
L'espansione dei comandi rimuove i newline in coda:
S="$(printf "a\n")"
printf "$S" | od -tx1
Uscite:
0000000 61
0000001
Questo rompe il metodo ingenuo di leggere dai file:
FILE="$(mktemp)"
printf "a\n\n" > "$FILE"
S="$(<"$FILE")"
printf "$S" | od -tx1
rm "$FILE"
Soluzione POSIX: aggiungere un carattere extra all'espansione del comando e rimuoverlo in seguito:
S="$(cat $FILE; printf a)"
S="${S%a}"
printf "$S" | od -tx1
Uscite:
0000000 61 0a 0a
0000003
Quasi POSIX workaround: Codifica ASCII. Vedi sotto.
Rimozione del carattere NUL
Non esiste un modo sano di Bash per memorizzare i caratteri NUL nelle variabili.
Questo colpisce sia le soluzioni di espansione che di lettura
, e non conosco nessun buon workaround per questo.
Esempio:
printf "a\0b" | od -tx1
S="$(printf "a\0b")"
printf "$S" | od -tx1
Uscite:
0000000 61 00 62
0000003
0000000 61 62
0000002
Ah, il nostro NUL è sparito!
Soluzioni:
Codifica ASCII. Vedi sotto.
usare l'estensione bash $""
letterali:
S=$"a0b"
printf "$S" | od -tx1
Funziona solo per i letterali, quindi non è utile per leggere da file.
Rimedio per le insidie
Memorizzare una versione codificata uuencode base64 del file nella variabile, e decodificare prima di ogni utilizzo:
FILE="$(mktemp)"
printf "a\0\n" > "$FILE"
S="$(uuencode -m "$FILE" /dev/stdout)"
uudecode -o /dev/stdout <(printf "$S") | od -tx1
rm "$FILE"
Output:
0000000 61 00 0a
0000003
uuencode e udecode sono POSIX 7 ma non in Ubuntu 12.04 di default (pacchetto sharutils
)... Non vedo un'alternativa POSIX 7 per l'estensione di sostituzione del processo bash <()
, tranne la scrittura su un altro file...
Naturalmente, questo è lento e scomodo, quindi credo che la vera risposta sia: non usare Bash se il file di input può contenere caratteri NUL.