¿Por qué un bash here-string agrega un carácter de línea nueva al final?

34

Los siguientes ejemplos muestran que se agrega una nueva línea a una cadena aquí .
¿Por qué se hace esto?

xxd -p <<<'a'  
# output: 610a

xxd -p <<<'a
'
# output: 610a0a
Peter.O
fuente

Respuestas:

38

La respuesta fácil es porque ksh está escrito de esa manera (y bash es compatible). Pero hay una razón para esa elección de diseño.

La mayoría de los comandos esperan entrada de texto. En el mundo de Unix, un archivo de texto consiste en una secuencia de líneas, cada una terminando en una nueva línea . Entonces, en la mayoría de los casos se requiere una nueva línea final. Un caso especialmente común es tomar la salida de un comando con una sustitución de comando, procesarlo de alguna manera y luego pasarlo a otro comando. La sustitución del comando elimina las nuevas líneas finales; <<<pone uno de vuelta.

tmp=$(foo)
tmp=${tmp//hello/world}
tmp=${tmp#prefix}
bar <<<$tmp

Bash y ksh no pueden manipular datos binarios de todos modos (no puede hacer frente a caracteres nulos), por lo que no es sorprendente que sus instalaciones estén orientadas a datos de texto.

La <<<sintaxis here-string es principalmente solo por conveniencia de todos modos, como <<here-documents. Si no necesita agregar una nueva línea final, use echo -n(en bash) oy printfuna tubería.

Gilles 'SO- deja de ser malvado'
fuente
Mucho más completo que mi respuesta.
Mike
2
Bash puede haber prestado aquí cadenas de ksh93, pero ksh a su vez las tomó prestadas de zsh, que las obtuvo del plan 9 shell rc .
Mark Reed
2
<<<fue introducido al mundo Bourne por zsh, no ksh. Y fue inspirado por un operador similar en el puerto Unix del rccual no agregó ese carácter adicional de nueva línea. Curiosamente, el =(<<<text)operador no agrega esa nueva línea zsh.
Stéphane Chazelas
Si te preguntas sobre el interés en esta respuesta es por esta pregunta en SO .
fedorqui
1
¿Hay alguna forma de escribir la cadena here (sin usar ninguna otra utilidad como printf, etc.) evitando la nueva línea de cola bash? Como @ StéphaneChazelas señaló es posible en zsh.
CTodea
3

Un escenario en el que es práctico agregar nuevas líneas a las cadenas aquí es cuando se usa el readcomando cuando el set -emodo está activo. Recuerde que set -ehace que una secuencia de comandos finalice cuando (más o menos) encuentra declaraciones que generan un código de estado distinto de cero. Tenga en cuenta que readgenera un código de estado distinto de cero cuando encuentra una cadena sin líneas nuevas:

#!/bin/bash
set -e

# The following statement succeeds because here-strings append a newline:
IFS='' read -r <<< 'newline appended'
echo 'Made it here'

# The following statement fails because 'read' returns a non-zero status
# code when no newlines are encountered.
printf 'no newline' | IFS='' read -r
echo 'Did not make it here'
Dejay Clayton
fuente
-3

Creo que esa es la única forma de obtener una nueva línea al final de una prueba aquí:

xxd <<<`echo -ne "a\n"`

Parece que el operador here-string elimina las nuevas líneas a menos que se indiquen en la sintaxis que envió.

Micro
fuente
44
Es la sustitución del comando la que está quitando la nueva línea final. Podrías simplificar esto a xxd <<<$(echo a).
Gilles 'SO- deja de ser malvado'