Duas armadilhas importantes
que foram ignoradas por outras respostas até agora:
- Trailing remoção de nova linha da expansão de comando
- Remoção de caracteres NUL
Trailing remoção de nova linha da expansão de comando
Este é um problema para o:
value="$(cat config.txt)"
soluções de tipo, mas não para read
soluções baseadas.
A expansão de comandos remove as novas linhas finais:
S="$(printf "a\n")"
printf "$S" | od -tx1
Saídas:
0000000 61
0000001
Isso quebra o método ingênuo de ler arquivos:
FILE="$(mktemp)"
printf "a\n\n" > "$FILE"
S="$(<"$FILE")"
printf "$S" | od -tx1
rm "$FILE"
Solução alternativa POSIX: acrescente um caractere extra à expansão do comando e remova-o posteriormente:
S="$(cat $FILE; printf a)"
S="${S%a}"
printf "$S" | od -tx1
Saídas:
0000000 61 0a 0a
0000003
Solução alternativa quase POSIX: codificação ASCII. Ver abaixo.
Remoção de caracteres NUL
Não há uma maneira sadia do Bash para armazenar caracteres NUL em variáveis .
Isso afeta a expansão e as read
soluções, e não conheço nenhuma solução alternativa para isso.
Exemplo:
printf "a\0b" | od -tx1
S="$(printf "a\0b")"
printf "$S" | od -tx1
Saídas:
0000000 61 00 62
0000003
0000000 61 62
0000002
Ha, nosso NUL se foi!
Soluções alternativas:
Codificação ASCII. Ver abaixo.
use $""
literais de extensão bash :
S=$"a\0b"
printf "$S" | od -tx1
Funciona apenas para literais, portanto, não é útil para ler arquivos.
Solução alternativa para as armadilhas
Armazene uma versão codificada em uuencode base64 do arquivo na variável e 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"
Resultado:
0000000 61 00 0a
0000003
uuencode e udecode são POSIX 7, mas não no Ubuntu 12.04 por padrão ( sharutils
pacote) ... Não vejo uma alternativa POSIX 7 para a <()
extensão de substituição do processo bash, exceto a gravação em outro arquivo ...
Claro, isso é lento e inconveniente, então acho que a resposta real é: não use Bash se o arquivo de entrada puder conter caracteres NUL.
cat
ou$(<someFile)
resultará em uma saída incompleta (o tamanho é menor que o arquivo real).