¿Por qué bash elimina \ n en $ (archivo cat)?

24

Si tengo el archivo que input.txtcontiene:

hello
world
!

Luego, ejecutar el comando bash echo $(cat input.txt)generará esto:

hello world !

¿Por qué y cómo puedo arreglarlo para que muestre exactamente lo que está en el archivo y cómo está en el archivo?

f.ardeliano
fuente

Respuestas:

32

Si utiliza

echo "$(cat input.txt)"

Funcionará correctamente.

Probablemente la entrada de eco está separada por líneas nuevas, y la manejará como comandos separados, por lo que el resultado será sin líneas nuevas.

arriano
fuente
¡Agradable! Entonces, ¿cuál es la diferencia (si la hay) entre $ () y backticks? (Lo siento si esto es demasiado tangencial)
Chan-Ho Suh
Son equivalentes, excepto por el hecho de que $ (...) es más fácil de anidar. En ambos casos, si no cita el resultado, se tokenizará en múltiples argumentos sobre espacios en blanco.
James Henstridge
3
Pero se omite el carácter de nueva línea final , incluso entre comillas dobles. Por el contrario, el operador de retroceso de Perl se expande a toda la salida del comando, incluidas todas las líneas nuevas.
Keith Thompson
66
@KeithThompson sí, la sustitución de comandos elimina todas las nuevas líneas finales de la salida. Eso tiene la ventaja de, por ejemplo, echo "$(date) something"eliminar la nueva línea final de la salida de la fecha, haciendo que ese eco muestre la fecha y "algo" en la misma línea. Si necesita almacenar un archivo o salida de comando "tal cual", use mapfile ( help mapfile) read -rd ''o un ciclo de lectura while.
geirha
Gracias a todos :-) ¡Aprendí algo de cada comentario aquí!
Chan-Ho Suh
2

Citado de la página de manual de bash, sección Command Substitution:

Las líneas nuevas incrustadas no se eliminan, pero pueden eliminarse durante la división de palabras.

Un poco más allá, misma sección:

Si la sustitución aparece entre comillas dobles, la división de palabras y la expansión del nombre de ruta no se realizan en los resultados.

Por eso echo "$(cat /etc/passwd)" funciona.

Además, se debe tener en cuenta que la sustitución de comandos por las especificaciones POSIX elimina las nuevas líneas finales:

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

Por lo tanto, la salida de un archivo a través de $(cat file.txt)puede conducir a la pérdida de nuevas líneas finales, y eso puede ser un problema si la integridad del archivo completo es la prioridad.

Sergiy Kolodyazhnyy
fuente
2

Puede conservar las nuevas líneas, por ejemplo, configurando IFS para vaciar:

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