Quero ler um arquivo e salvá-lo na variável, mas preciso manter a variável e não apenas imprimir o arquivo. Como posso fazer isso? Eu escrevi este script, mas não é exatamente o que eu precisava:
#!/bin/sh
while read LINE
do
echo $LINE
done <$1
echo 11111-----------
echo $LINE
No meu script, posso fornecer o nome do arquivo como parâmetro, portanto, se o arquivo contiver "aaaa", por exemplo, ele imprimirá o seguinte:
aaaa
11111-----
Mas isso apenas imprime o arquivo na tela e quero salvá-lo em uma variável! Existe uma maneira fácil de fazer isso?
cat
ou$(<someFile)
resultará em uma saída incompleta (o tamanho é menor que o arquivo real).Respostas:
Na plataforma cruzada, o menor denominador comum
sh
você usa:Em
bash
ouzsh
, para ler um arquivo inteiro em uma variável sem chamarcat
:Invocando
cat
embash
ouzsh
slurp um arquivo seria considerado um uso inútil de gato .Observe que não é necessário citar a substituição de comando para preservar novas linhas.
Veja: Wiki do Bash Hacker - Substituição de comandos - Especialidades .
fonte
value="`cat config.txt`"
evalue="$(<config.txt)"
seria mais seguro no caso de o config.txt conter espaços?cat
como acima nem sempre é considerado um uso inútil decat
. Por exemplo,< invalid-file 2>/dev/null
resultará em uma mensagem de erro que não pode ser roteada para/dev/null
, enquantocat invalid-file 2>/dev/null
é roteada corretamente para/dev/null
.value=$(<config.txt)
é bom, masvalue = $(<config.txt)
é ruim. Cuidado com esses espaços.Se você quiser ler o arquivo inteiro em uma variável:
Se você quiser ler linha por linha:
fonte
echo "$value"
. Caso contrário, o shell executará tokenização de espaço em branco e expansão de curinga no valor.read -r
vez de apenasread
- sempre, a menos que você exija especificamente o estranho comportamento herdado ao qual você está se referindo.Duas armadilhas importantes
que foram ignoradas por outras respostas até agora:
Trailing remoção de nova linha da expansão de comando
Este é um problema para o:
soluções de tipo, mas não para
read
soluções baseadas.A expansão de comandos remove as novas linhas finais:
Saídas:
Isso quebra o método ingênuo de ler arquivos:
Solução alternativa POSIX: acrescente um caractere extra à expansão do comando e remova-o posteriormente:
Saídas:
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:
Saídas:
Ha, nosso NUL se foi!
Soluções alternativas:
Codificação ASCII. Ver abaixo.
use
$""
literais de extensão bash :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:
Resultado:
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.
fonte
S="$(printf "\\\'\"")"; echo $S
. Saída:\'"
. Por isso, funciona =)$()
expansão, meu exemplo mostra que a$()
expansão funciona\'"
.isso funciona para mim:
v=$(cat <file_path>) echo $v
fonte
Como Ciro Santilli observa, o uso de substituições de comandos eliminará as novas linhas à direita. A solução alternativa para adicionar caracteres à direita é ótima, mas depois de usá-lo por um bom tempo, decidi que precisava de uma solução que não usasse a substituição de comandos.
Minha abordagem agora usa
read
junto com a flagprintf
do builtin para ler o conteúdo do stdin diretamente em uma variável.-v
Isso suporta entradas com ou sem novas linhas à direita.
Exemplo de uso:
fonte
_contents="${_contents}${_line}\n "
para preservar novas linhas?$'\n'
? Isso é necessário, caso contrário, você anexará literal\
en
caracteres. Seu bloco de código também possui um espaço extra no final, não tenho certeza se isso é intencional, mas recuava todas as linhas subseqüentes com um espaço em branco extra.Você pode acessar 1 linha por vez usando o loop for
Copie todo o conteúdo para o arquivo (diga line.sh); Executar
fonte
for
loop não passa por linhas, passa por cima de palavras. No caso de/etc/passwd
, acontece que cada linha contém apenas uma palavra. No entanto, outros arquivos podem conter várias palavras por linha.