Cómo agregar nuevas líneas al usar echo


42

¿Por qué el siguiente comando no inserta nuevas líneas en el archivo generado y cuál es la solución?

$ echo "Line 1\r\nLine2" >> readme.txt

$ cat readme.txt 
Line 1\r\nLine2

66
Es echoobligatorio? puedes usar printf.
Archemar

No sabía acerca de printf, con printf funciona: P ... entonces, ¿qué hace que no funcione con echo entonces?
Saeid Yazdani

¿Se \rincluye en la salida o es parte de la CRLFnueva línea?
cuonglm

99
Hay muchas implementaciones diferentes de echocomandos incompatibles entre sí. Por lo tanto, se recomienda utilizar una herramienta más estándar como printf. Consulte unix.stackexchange.com/questions/65803/… para obtener una descripción general ampliada del problema.
jimmij

Respuestas:


38

echo


Una echoimplementación que se ajusta estrictamente a la especificación Single Unix agregará nuevas líneas si lo hace:

echo 'line1\nline2'

Pero ese no es un comportamiento confiable. De hecho, realmente no hay ningún comportamiento estándar que pueda esperar echo.

Operandos

string

Una cadena que se escribirá en la salida estándar. Si el primer operando es -n, o si alguno de los operandos contiene un carácter de < \barra diagonal inversa> , los resultados están definidos por la implementación .

En sistemas conformes a XSI , si el primer operando es -n, se tratará como una cadena, no como una opción . Las siguientes secuencias de caracteres se reconocerán en sistemas conformes a XSI dentro de cualquiera de los argumentos:

\a- Escribe un <alert> .

\b- Escribe un <retroceso> .

\c- Suprima la <línea nueva> que de lo contrario sigue al argumento final en la salida. Todos los caracteres que siguen a los \cen los argumentos serán ignorados.

\f- Escriba un <form-feed> .

\n- Escribir una <nueva línea> .

\r- Escribe un <carriage-return> .

\t- Escribe una <tab> .

\v- Escribe un <vertical-tab> .

\\- Escriba un carácter <backslash> .

\0num- Escriba un valor de 8 bits que sea el número octal de cero, uno, dos o tres dígitos num.

Por lo tanto, no existe una forma general de saber cómo escribir una nueva línea echo, excepto que generalmente puede confiar en hacerlo echo.

Un bashshell normalmente no se ajusta a la especificación y maneja las -ny otras opciones, pero incluso eso es incierto. Tu puedes hacer:

shopt -s xpg_echo
echo hey\\nthere

hey
there

Y ni siquiera eso es necesario si bashse ha construido con la opción de tiempo de construcción ...

--enable-xpg-echo-default

Haga que el echobuiltin expanda caracteres de escape con barra invertida de forma predeterminada, sin requerir la -eopción. Esto establece el valor predeterminado de la xpg_echoopción de shell en on, lo que hace que el Bash se echocomporte más como la versión especificada en la Especificación Single Unix, versión 3. Consulte Bash Builtins , para obtener una descripción de las secuencias de escape que echoreconoce.


printf


Por otro lado, printfel comportamiento es bastante manso en comparación.

RAZÓN FUNDAMENTAL

La printfutilidad se agregó para proporcionar una funcionalidad que históricamente ha sido proporcionada por echo. Sin embargo, debido a las diferencias irreconciliables en las diversas versiones echoexistentes, la versión tiene pocas características especiales, dejando estas a esta nueva printfutilidad, que se basa en una en el sistema de la Novena Edición.

La sección DESCRIPCIÓN EXTENDIDA coincide casi exactamente con la printf()función en el estándar ISO C, aunque se describe en términos de notación de formato de archivo en notación de formato de archivo XBD .

Maneja cadenas de formato que describen sus argumentos, que pueden ser cualquier cantidad de cosas, pero las cadenas son prácticamente %bcadenas de yte o %strings literales . Además de los %formats en el primer argumento, se comporta más como un %bargumento de cadena yte, excepto que no maneja el \cescape.

printf ^%b%s$ '\n' '\n' '\t' '\t'

^
\n$^    \t$

Ver ¿Por qué es printfmejor que echo? para más.


echo() printf


Puede escribir sus propios estándares conformes echocomo ...

echo(){
    printf '%b ' "$@\n\c"
}

... que casi siempre debería hacer lo correcto automáticamente.

En realidad, no ... Eso imprime un literal \nen la cola de los argumentos si el último argumento termina en un número impar de <backslashes> .

Pero esto no:

echo()
    case    ${IFS- } in
    (\ *)   printf  %b\\n "$*";;
    (*)     IFS=\ $IFS
            printf  %b\\n "$*"
            IFS=${IFS#?}
    esac

+1 para la shopt -s xpg_echoopción echode usar -epor defecto.
Vignesh Raja

Esta solución no funciona sin ella -e. Me sorprende que nadie se haya dado cuenta, excepto quizás @HaydeSchiff
ha9u63ar

@ ha9u63ar - uhh ... ¿leíste esto?
mikeserv

27

Pase la bandera -e a echo para que analice caracteres escapados como "\ r \ n", de esta manera:

echo -e "Line 1\r\nLine2" >> readme.txt

Una buena opción "-e" para hacer que funcionen las secuencias de escape: dice en otra respuesta que echono es confiable y no sigue los estándares a diferencia printf.
Edward

1
Asegúrese de que su script no contenga ningún \ r \ n literal, como en un tr -d "\n"comando.
Noumenon

8

En todas las versiones de bash que he usado, simplemente puede insertar una nueva línea literal en una cadena de forma interactiva o en un script, siempre que la cadena esté suficientemente citada.

Interactivamente:

$ echo "Line one
> Line two"
Line one
Line two
$

En un guion:

echo "Line one
Line two"

4
echo -e "Line 1\r\nLine2" >> readme.txt

Posibilidades de uso adicionales:

man echo

2

La gente ya ha respondido adecuadamente, pero me niego a aceptar un mundo donde echo acepta cualquier otra opción que no sea -n.

nl='
'
echo Line 1"$nl"Line 2"$nl"Line 3

1

Si tiene un carácter que no forma parte del mensaje, puede canalizarlo a través de sed

$ echo "Time on the next line:@$(date +"%Y-%m-%dT%T%z")" | sed -e's/@/\n/g'
Time on the next line:
2016-03-25T10:12:39-0500
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.