Due insidie importanti
che finora sono state ignorate da altre risposte:
- Trailing rimozione di newline dall'espansione dei comandi
- Rimozione del carattere NUL
Trailing rimozione di newline dall'espansione dei comandi
Questo è un problema per:
value="$(cat config.txt)"
soluzioni di tipo, ma non per read
soluzioni basate.
L'espansione dei comandi rimuove le nuove righe finali:
S="$(printf "a\n")"
printf "$S" | od -tx1
Uscite:
0000000 61
0000001
Questo rompe il metodo ingenuo di lettura dai file:
FILE="$(mktemp)"
printf "a\n\n" > "$FILE"
S="$(<"$FILE")"
printf "$S" | od -tx1
rm "$FILE"
Soluzione alternativa POSIX: aggiungere un ulteriore carattere 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
Soluzione quasi POSIX: codifica ASCII. Vedi sotto.
Rimozione del carattere NUL
Non esiste un modo Bash sano per memorizzare i caratteri NUL in variabili .
Ciò influisce sia sull'espansione che sulle read
soluzioni e non conosco alcuna soluzione alternativa.
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 alternative:
Codifica ASCII. Vedi sotto.
usa $""
letterali di estensione bash :
S=$"a\0b"
printf "$S" | od -tx1
Funziona solo con valori letterali, quindi non è utile per leggere da file.
Soluzione alternativa per le insidie
Archivia una versione codificata uuencode base64 del file nella variabile e decodifica 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"
Produzione:
0000000 61 00 0a
0000003
uuencode e udecode sono POSIX 7 ma non in Ubuntu 12.04 per impostazione predefinita ( sharutils
pacchetto) ... Non vedo un'alternativa POSIX 7 per l' <()
estensione di sostituzione del processo bash tranne la scrittura in un altro file ...
Naturalmente, questo è lento e scomodo, quindi immagino che la vera risposta sia: non usare Bash se il file di input può contenere caratteri NUL.
cat
o$(<someFile)
si tradurrà in un'uscita incompleta (la dimensione è inferiore al file vero e proprio).