¿Cómo evitar la sustitución del comando bash para eliminar el carácter de nueva línea?

Para acelerar un poco la ejecución del script bash, me gustaría mantener el resultado de un comando en una variable usando la sustitución de comando, pero la sustitución del comando reemplaza el carácter de nueva línea 0x0A por un espacio. Por ejemplo:

 a=`df -H` 

o

 a=$( df -H ) 

Cuando quiero procesar más $a , los caracteres de nueva línea son reemplazados por un espacio y todas las líneas están ahora en una línea, que es mucho más difícil de grep:

 echo $a 

¿Cuáles serían los trucos más fáciles para evitar que el carácter de nueva línea sea eliminado por la sustitución del comando?

Las nuevas líneas no seguidas no se eliminan

Las líneas nuevas que está buscando están allí, simplemente no las ve, porque usa el echo sin citar la variable.

Validación :

 $ a=$( df -H ) $ echo $a Filesystem Size Used Avail Use% Mounted on /dev/sda3 276G 50G 213G 19% / udev 2.1G 4.1k 2.1G 1% /dev tmpfs 832M 820k 832M 1% /run none 5.3M 0 5.3M 0% /run/lock none 2.1G 320k 2.1G 1% /run/shm $ echo "$a" Filesystem Size Used Avail Use% Mounted on /dev/sda3 276G 50G 213G 19% / udev 2.1G 4.1k 2.1G 1% /dev tmpfs 832M 820k 832M 1% /run none 5.3M 0 5.3M 0% /run/lock none 2.1G 320k 2.1G 1% /run/shm $ 

Las nuevas líneas de seguimiento se eliminan

Como @ user4815162342 señaló correctamente, aunque las líneas nuevas dentro de la salida no se eliminan, las líneas nuevas posteriores se eliminan con la sustitución de comandos. Ver experimento a continuación:

 $ a=$'test\n\n' $ echo "$a" test $ b=$(echo "$a") $ echo "$b" test $ 

En la mayoría de los casos esto no importa, porque echo agregará la nueva línea eliminada (a menos que se invoque con la opción -n ), pero hay algunos casos extremos en los que hay más de una línea nueva en la salida de un progtwig, y son importantes por alguna razón.

Soluciones provisionales

1. Agregar un carácter ficticio

En estos casos, como se mencionó @Scrutinizer , puede usar la siguiente solución alternativa:

 $ a=$(printf 'test\n\n'; printf x); a=${a%x} $ echo "$a" test $ 

Explicación: El carácter x se agrega a la salida (usando printf x ), después de las nuevas líneas. Como las líneas nuevas ya no van más lejos, no se eliminan mediante la sustitución de comandos. El siguiente paso es eliminar la x que agregamos, usando el operador % en ${a%x} . ¡Ahora tenemos la salida original, con todas las novedades presentes!

2. Leer usando sustitución de proceso

En lugar de utilizar la sustitución de comandos para asignar la salida de un progtwig a variable, podemos utilizar la sustitución de proceso para alimentar la salida del progtwig al comando integrado de read (crédito a @ormaaj ). La sustitución de procesos conserva todas las nuevas líneas. Leer el resultado a una variable es un poco complicado, pero puedes hacerlo así:

 $ IFS= read -rd '' var < <( printf 'test\n\n' ) $ echo "$var" test $ 

Explicación:

  • Configuramos el separador de campo interno para que el comando de lectura sea nulo, con IFS= . De lo contrario, read no asignaría todo el resultado a var , sino solo al primer token.
  • Invocamos read con opciones -rd '' . La r es para evitar que la barra diagonal inversa actúe como un carácter especial, y con d '' establece el delimitador en nada, para que read lea toda la salida, en lugar de solo la primera línea.

3. Leer de una tubería

En lugar de usar la sustitución de comando o proceso para asignar la salida de un progtwig a variable, podemos canalizar la salida del progtwig al comando de read (crédito a @ormaaj ). Piping también conserva todas las líneas nuevas. Sin embargo, lastpipe cuenta que esta vez configuramos el comportamiento opcional del shell lastpipe , utilizando el shopt incorporado . Esto es obligatorio para que el comando de read se ejecute en el entorno de shell actual. De lo contrario, la variable se asignará en una subshell y no será accesible desde el rest de la secuencia de comandos.

 $ cat test.sh #!/bin/bash shopt -s lastpipe printf "test\n\n" | IFS= read -rd '' var echo "$var" $ ./test.sh test $ 

Estaba tratando de entender esto porque estaba usando bash para transmitir el resultado de ejecutar el intérprete en un script F #. Después de un poco de prueba y error, esto resultó para resolver el problema:

 $ cat fsi.ch #!/bin/bash echo "$(fsharpi --quiet --exec --nologo $1)" $ fsi.ch messages.fsx Welcome to my program. Choose from the menu: new | show | remove 

Suponiendo, por supuesto, que necesita ejecutar un progtwig de terminal. Espero que esto ayude.