Zwei wichtige Fallstricke
die bisher von anderen Antworten ignoriert wurden:
- Nachfolgendes Entfernen von Zeilenumbrüchen aus der Befehlserweiterung
- NUL Zeichenentfernung
Nachfolgendes Entfernen von Zeilenumbrüchen aus der Befehlserweiterung
Dies ist ein Problem für:
value="$(cat config.txt)"
Typ Lösungen, aber nicht für read
basierte Lösungen.
Die Befehlserweiterung entfernt nachgestellte Zeilenumbrüche:
S="$(printf "a\n")"
printf "$S" | od -tx1
Ausgänge:
0000000 61
0000001
Dies unterbricht die naive Methode zum Lesen aus Dateien:
FILE="$(mktemp)"
printf "a\n\n" > "$FILE"
S="$(<"$FILE")"
printf "$S" | od -tx1
rm "$FILE"
POSIX-Problemumgehung: Fügen Sie der Befehlserweiterung ein zusätzliches Zeichen hinzu und entfernen Sie es später:
S="$(cat $FILE; printf a)"
S="${S%a}"
printf "$S" | od -tx1
Ausgänge:
0000000 61 0a 0a
0000003
Fast POSIX-Problemumgehung: ASCII-Codierung. Siehe unten.
NUL Zeichenentfernung
Es gibt keine vernünftige Bash-Methode, um NUL-Zeichen in Variablen zu speichern .
Dies wirkt sich sowohl auf die Erweiterung als auch auf die read
Lösungen aus, und ich kenne keine gute Problemumgehung dafür.
Beispiel:
printf "a\0b" | od -tx1
S="$(printf "a\0b")"
printf "$S" | od -tx1
Ausgänge:
0000000 61 00 62
0000003
0000000 61 62
0000002
Ha, unser NUL ist weg!
Problemumgehungen:
ASCII-Codierung. Siehe unten.
Verwenden Sie Bash-Erweiterungsliterale $""
:
S=$"a\0b"
printf "$S" | od -tx1
Funktioniert nur für Literale und ist daher nicht zum Lesen aus Dateien geeignet.
Problemumgehung für die Fallstricke
Speichern Sie eine uuencode base64-codierte Version der Datei in der Variablen und dekodieren Sie sie vor jeder Verwendung:
FILE="$(mktemp)"
printf "a\0\n" > "$FILE"
S="$(uuencode -m "$FILE" /dev/stdout)"
uudecode -o /dev/stdout <(printf "$S") | od -tx1
rm "$FILE"
Ausgabe:
0000000 61 00 0a
0000003
uuencode und udecode sind POSIX 7, aber standardmäßig nicht in Ubuntu 12.04 ( sharutils
Paket) ... Ich sehe keine POSIX 7-Alternative für die Bash-Prozess- <()
Ersetzungserweiterung, außer in eine andere Datei zu schreiben ...
Dies ist natürlich langsam und unpraktisch, daher lautet die eigentliche Antwort: Verwenden Sie Bash nicht, wenn die Eingabedatei NUL-Zeichen enthalten kann.
cat
oder$(<someFile)
führen zu einer unvollständigen Ausgabe (die Größe ist geringer als die tatsächliche Datei).