Dwie ważne pułapki
które zostały dotychczas zignorowane przez inne odpowiedzi:
- Końcowe usuwanie nowego wiersza z rozszerzenia poleceń
- Usuwanie znaków NUL
Końcowe usuwanie nowego wiersza z rozszerzenia poleceń
Jest to problem dla:
value="$(cat config.txt)"
rozwiązania typu, ale nie dla read
rozwiązań opartych.
Rozszerzenie poleceń usuwa końcowe znaki nowej linii:
S="$(printf "a\n")"
printf "$S" | od -tx1
Wyjścia:
0000000 61
0000001
To łamie naiwną metodę czytania z plików:
FILE="$(mktemp)"
printf "a\n\n" > "$FILE"
S="$(<"$FILE")"
printf "$S" | od -tx1
rm "$FILE"
Obejście POSIX: dodaj dodatkowy znak do rozszerzenia polecenia i usuń go później:
S="$(cat $FILE; printf a)"
S="${S%a}"
printf "$S" | od -tx1
Wyjścia:
0000000 61 0a 0a
0000003
Obejście prawie POSIX: kodowanie ASCII. Patrz poniżej.
Usuwanie znaków NUL
Nie ma rozsądnego sposobu na przechowywanie znaków NUL w zmiennych .
Wpływa to zarówno na rozwój, jak i na read
rozwiązania, i nie znam na to żadnego dobrego obejścia.
Przykład:
printf "a\0b" | od -tx1
S="$(printf "a\0b")"
printf "$S" | od -tx1
Wyjścia:
0000000 61 00 62
0000003
0000000 61 62
0000002
Ha, nasz NUL zniknął!
Obejścia:
Kodowanie ASCII. Patrz poniżej.
użyj $""
literałów rozszerzenia bash :
S=$"a\0b"
printf "$S" | od -tx1
Działa tylko z literałami, więc nie jest przydatny do czytania z plików.
Obejście problemów
Przechowuj wersję pliku zakodowaną w formacie uuencode base64 w zmiennej i dekoduj przed każdym użyciem:
FILE="$(mktemp)"
printf "a\0\n" > "$FILE"
S="$(uuencode -m "$FILE" /dev/stdout)"
uudecode -o /dev/stdout <(printf "$S") | od -tx1
rm "$FILE"
Wynik:
0000000 61 00 0a
0000003
uuencode i udecode są POSIX 7, ale domyślnie nie są dostępne w Ubuntu 12.04 ( sharutils
pakiet) ... Nie widzę alternatywy POSIX 7 dla <()
rozszerzenia podstawiania procesu bash oprócz zapisu do innego pliku ...
Oczywiście jest to powolne i niewygodne, więc sądzę, że prawdziwa odpowiedź brzmi: nie używaj Bash, jeśli plik wejściowy może zawierać znaki NUL.
cat
lub$(<someFile)
spowoduje niekompletne wyjście (rozmiar jest mniejszy niż rzeczywisty plik).