Zwei wichtige Fallstricke
die in anderen Antworten bisher ignoriert wurden:
- Entfernen von nachgestellten Zeilenumbrüchen aus Befehlserweiterungen
- NUL-Zeichen entfernen
Entfernung von Zeilenumbrüchen aus der Befehlserweiterung
Dies ist ein Problem für die:
value="$(cat config.txt)"
Lösungen, nicht aber für read
basierte Lösungen.
Bei der Befehlsexpansion werden nachfolgende Zeilenumbrüche entfernt:
S="$(printf "a\n")"
printf "$S" | od -tx1
Ausgänge:
0000000 61
0000001
Dadurch wird die naive Methode des Lesens von Dateien durchbrochen:
FILE="$(mktemp)"
printf "a\n\n" > "$FILE"
S="$(<"$FILE")"
printf "$S" | od -tx1
rm "$FILE"
POSIX-Umgehung: Fügen Sie ein zusätzliches Zeichen an die Befehlserweiterung an 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-Umgehung: ASCII-Kodierung. Siehe unten.
NUL-Zeichen entfernen
Es gibt keinen vernünftigen Bash-Weg, um NUL-Zeichen in Variablen zu speichern .
Dies betrifft sowohl die Expansion als auch die read
Lösungen, und ich kenne keine gute Umgehung für dieses Problem.
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!
Umgehungen:
-
ASCII-Kodierung. Siehe unten.
-
Bash-Erweiterung verwenden $""
Literale:
S=$"a\0b"
printf "$S" | od -tx1
Funktioniert nur für Literale, also nicht für das Lesen aus Dateien.
Abhilfe für die Fallstricke
Speichern Sie eine uuencode base64 kodierte 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 nicht in Ubuntu 12.04 standardmäßig ( sharutils
Paket)... Ich sehe keine POSIX 7 Alternative für den Bash-Prozess <()
Substitutionserweiterung außer dem Schreiben in eine andere Datei...
Das ist natürlich langsam und unbequem, also lautet die Antwort wohl: Verwenden Sie die Bash nicht, wenn die Eingabedatei NUL-Zeichen enthalten kann.