Dos trampas importantes
que fueron ignoradas por otras respuestas hasta ahora:
- Eliminación de línea nueva posterior a la expansión del comando
- Eliminación de caracteres NUL
Eliminación de línea nueva posterior a la expansión del comando
Este es un problema para:
value="$(cat config.txt)"
soluciones de tipo, pero no para read
soluciones basadas.
La expansión de comandos elimina las nuevas líneas finales:
S="$(printf "a\n")"
printf "$S" | od -tx1
Salidas:
0000000 61
0000001
Esto rompe el método ingenuo de lectura de archivos:
FILE="$(mktemp)"
printf "a\n\n" > "$FILE"
S="$(<"$FILE")"
printf "$S" | od -tx1
rm "$FILE"
Solución alternativa de POSIX: agregue un carácter adicional a la expansión del comando y elimínelo más tarde:
S="$(cat $FILE; printf a)"
S="${S%a}"
printf "$S" | od -tx1
Salidas:
0000000 61 0a 0a
0000003
Solución alternativa casi POSIX: codificación ASCII. Vea abajo.
Eliminación de caracteres NUL
No hay una forma sensata de Bash de almacenar caracteres NUL en variables .
Esto afecta tanto a la expansión como a las read
soluciones, y no conozco una buena solución para ello.
Ejemplo:
printf "a\0b" | od -tx1
S="$(printf "a\0b")"
printf "$S" | od -tx1
Salidas:
0000000 61 00 62
0000003
0000000 61 62
0000002
Ja, nuestro NUL se ha ido!
Soluciones alternativas:
Codificación ASCII. Vea abajo.
usar $""
literales de extensión bash :
S=$"a\0b"
printf "$S" | od -tx1
Solo funciona para literales, por lo que no es útil para leer archivos.
Solución para las trampas
Almacene una versión codificada uuencode base64 del archivo en la variable y decodifique antes de cada uso:
FILE="$(mktemp)"
printf "a\0\n" > "$FILE"
S="$(uuencode -m "$FILE" /dev/stdout)"
uudecode -o /dev/stdout <(printf "$S") | od -tx1
rm "$FILE"
Salida:
0000000 61 00 0a
0000003
uuencode y udecode son POSIX 7 pero no en Ubuntu 12.04 por defecto ( sharutils
paquete) ... No veo una alternativa POSIX 7 para la <()
extensión de sustitución del proceso bash, excepto escribir en otro archivo ...
Por supuesto, esto es lento e inconveniente, así que supongo que la respuesta real es: no use Bash si el archivo de entrada puede contener caracteres NUL.
cat
o$(<someFile)
dará como resultado una salida incompleta (el tamaño es menor que el archivo real).