Por que o bash remove \ n em $ (arquivo cat)?

24

Se eu tiver o arquivo que input.txtcontém:

hello
world
!

A execução do comando bash echo $(cat input.txt)produzirá o seguinte:

hello world !

Por que e como posso corrigi-lo para gerar exatamente o que está no arquivo, como está no arquivo?

f.ardelian
fonte

Respostas:

32

Se você usar

echo "$(cat input.txt)"

funcionará corretamente.

Provavelmente, a entrada de eco é separada por novas linhas, e será tratada como comandos separados, portanto o resultado será sem novas linhas.

ariano
fonte
Agradável! Então, qual é a diferença (se houver) entre $ () e backticks? (Desculpe se isso é muito tangencial)
Chan-Ho Suh
Eles são equivalentes, exceto pelo fato de que $ (...) é mais fácil de aninhar. Nos dois casos, se você não citar o resultado, ele será simbolizado em vários argumentos no espaço em branco.
James Henstridge
3
Mas o caractere de nova linha final é omitido, mesmo entre aspas duplas. Por outro lado, o operador backtick do Perl se expande para toda a saída do comando, incluindo todas as novas linhas.
amigos estão dizendo sobre keith thompson
6
@KeithThompson sim, a substituição de comandos remove todas as novas linhas à direita da saída. Isso tem a vantagem de, por exemplo, echo "$(date) something"retirar a nova linha à direita da saída da data, tornando esse eco a saída da data e "algo" na mesma linha. Se você precisar armazenar um arquivo ou saída de comando "como está", use mapfile ( help mapfile) read -rd ''ou um loop de leitura while.
Geirha #
Obrigado a todos :-) Eu aprendi algo com cada comentário aqui!
Chan-Ho Suh
2

Citado na página do manual do bash, seção Command Substitution:

As novas linhas incorporadas não são excluídas, mas podem ser removidas durante a divisão de palavras.

Um pouco mais, mesma seção:

Se a substituição aparecer entre aspas duplas, a divisão de palavras e a expansão do nome do caminho não são executadas nos resultados.

É por isso que echo "$(cat /etc/passwd)" funciona.

Além disso, é preciso estar ciente de que a substituição de comandos pelas especificações POSIX remove as novas linhas finais:

$ echo "$(printf "one\ntwo\n\n\n")"
one
two

Portanto, a saída de um arquivo via $(cat file.txt)pode levar à perda de novas linhas finais, e isso pode ser um problema se a integridade total do arquivo for prioritária.

Sergiy Kolodyazhnyy
fonte
2

Você pode preservar novas linhas, por exemplo, configurando o IFS para vazio:

$ IFS=
$ a=$(cat links.txt)
$ echo "$a"
link1
link2
link3
Sarnath Jegadeesan
fonte