¿Por qué `echo -e“ \\\ SOME_TEXT ”` muestra solo una barra invertida?

19

¿Podría alguien explicar qué está sucediendo detrás de escena en el escape de personajes en el shell de Linux? Intenté lo siguiente y busqué mucho en Google, sin ningún éxito en comprender qué (y cómo) está sucediendo:

root@sv01:~# echo -e "\ Hello!"
\ Hello!
root@sv01:~# echo -e "\\ Hello!"
\ Hello!
root@sv01:~# echo -e "\\\ Hello!"
\ Hello!
root@sv01:~# echo -e "\\\\ Hello!"
\ Hello!
root@sv01:~# echo -e "\\\\\ Hello!"
\\ Hello!
root@sv01:~# echo -e "\\\\\\ Hello!"
\\ Hello!
root@sv01:~# echo -e "\\\\\\\ Hello!"
\\ Hello!
root@sv01:~# echo -e "\\\\\\\\ Hello!"
\\ Hello!
root@sv01:~# echo -e "\\\\\\\\\ Hello!"
\\\ Hello!
root@sv01:~# echo -e "\n Hello!"

 Hello!
root@sv01:~# echo -e "\\n Hello!"

 Hello!
root@sv01:~# echo -e "\\\n Hello!"
\n Hello!

Estoy totalmente perdido allí, así que, por ejemplo, ¿por qué tres barras diagonales inversas solo dan una barra diagonal inversa? Esperaría: los dos primeros se escaparán a uno, el tercero no encontrará nada para escapar, por lo que seguirá siendo una barra oblicua (línea en el primer experimento), pero lo que está sucediendo es que el tercero simplemente desaparece.
¿Por qué obtengo una barra diagonal inversa de cuatro \\\\ Hello? Esperaría que cada par dé una barra diagonal inversa -> dos barras diagonales inversas.

¿Y por qué necesito tres barras invertidas en el último caso para \ n escapar? ¿Qué está pasando en el fondo de escapar para conseguir eso? ¿Y en qué se diferencia del \\ncaso?

Agradezco cualquier explicación de lo que está sucediendo en las líneas anteriores.

Mohammed Noureldin
fuente
echo -ede todos modos, el comportamiento no está definido por los estándares; consulte pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html . La salida está completamente definida por la implementación si hay una barra diagonal inversa en cualquier lugar de las entradas, y la única opción permitida es -n(lo que significa que una implementación que cumpla con los estándares tendrá una echo -eimpresión -een su salida).
Charles Duffy
... incluso si estás 100% seguro de que su cáscara es bash, incluso entonces echo -e no es seguro: echose comportará de acuerdo con la norma si ambos posixy xpg_echoestán habilitados en tiempo de ejecución opciones, o si compilados con opciones de tiempo de compilación equivalentes. La práctica segura es usar printfen su lugar: consulte las secciones USO DE LA APLICACIÓN y JUSTIFICACIÓN del enlace anterior que describe cómo hacer que printfactúe como un reemplazo echo.
Charles Duffy

Respuestas:

28

Esto es porque bashy echo -ecombinado. Desdeman 1 bash

Una barra invertida no citada ( \) es el carácter de escape. Conserva el valor literal del siguiente carácter que sigue, con la excepción de <newline>. [...]

Encerrar caracteres entre comillas dobles preserva el valor literal de todos los caracteres dentro de las comillas, con la excepción de $, `, \[...] La barra invertida mantiene su significado especial sólo cuando es seguida por uno de los siguientes caracteres: $,`, ", \, o <newline>.

El punto es: la barra invertida entre comillas dobles no siempre es especial.

Hay varias implementaciones de echoen general, es una función incorporada bash; Lo importante aquí es este comportamiento:

Si -eestá vigente, se reconocen las siguientes secuencias:
\\
barra invertida
[…]
\n
nueva línea

Ahora podemos decodificar:

  1. echo -e "\ Hello!"- nada especial para bash, nada especial para echo; \corsé.
  2. echo -e "\\ Hello!"- el primero \dice bashque trate al segundo \literalmente; echoobtiene \ Hello!y actúa como se indica arriba.
  3. echo -e "\\\ Hello!"- el primero \dice bashque trate al segundo \literalmente; echoobtiene \\ Hello!y (por -e) reconoce \\como \.
  4. echo -e "\\\\ Hello!"- el primero \dice bashque trate al segundo \literalmente; el tercero dice lo mismo del cuarto; echoobtiene \\ Hello!y (por -e) reconoce \\como \.
  5. echo -e "\\\\\ Hello!"- el primero \dice bashque trate al segundo \literalmente; el tercero dice lo mismo del cuarto; el último no es especial; echoobtiene \\\ Hello!y (debido a -e) reconoce la inicial \\como \, la última \permanece intacta.

Y así. Como puede ver, hasta cuatro barras invertidas consecutivas dan uno como resultado. Es por eso que necesita (al menos) nueve de ellos para obtener tres. 9 = 4 + 4 + 1.

Ahora con \n:

  1. echo -e "\n Hello!"- no hay nada especial para bash, echo obtiene la misma cadena y (debido a -e) interpreta \ncomo una nueva línea.
  2. echo -e "\\n Hello!"- bashinterpreta \\como \; echoobtiene \n Hello!y el resultado es el mismo que el anterior.
  3. echo -e "\\\n Hello!"- bashinterpreta la inicial \\como \; echoobtiene \\n Hello!y (debido a -e) se interpreta \\como un literal \que debe imprimirse.

Los resultados serían diferentes con en 'lugar de "(debido a un bashcomportamiento diferente ) o sin -e( echocomportamiento diferente ).

Kamil Maciorowski
fuente
1
¡Muchas gracias! Entonces, hay dos pasos de escape, el paso hecho por bash, y el segundo por -ejueces, el texto ya juzgado por bash, ¿es correcto? si eso es correcto, eso elimina la confusión. ¿Podrías mencionar cómo se sedcomporta? ¿Tiene su propia construcción en técnica de escape? entonces quiero decir, ¿se comporta como eco con -e?
Mohammed Noureldin
2
@MohammedNoureldin Sí, hay dos pasos. Su pregunta original está bien como está, no lo hagamos demasiado complicado sed. Sin embargo, puede hacer otra pregunta ( sedsolo sobre ), solo haga su propia investigación primero.
Kamil Maciorowski el
3
@MohammedNoureldin sedseguirá los mismos principios básicos: bash interpretará la línea de comando de acuerdo con sus reglas, analizando (y tal vez eliminando) las comillas y los escapes. El resultado de eso se pasa a sed, que lo interpreta de acuerdo con sus reglas de escape. Por cierto, puede simplificar esto usando una cadena entre comillas simples bash, ya que eso no tiene una interpretación de escape simple hecha (por bash): bash elimina las comillas simples y pasa lo que está dentro de ellas directamente al comando.
Gordon Davisson
Todavía tengo un pequeño problema por echo -e "\\\n Hello!"si acaso. Aquí bash escapará , y se convertirá \\n, luego -eescapará de las dos barras invertidas resultantes \\ny luego se convertirán \n. ahora quien interpreta \npara que sea nueva línea? Normalmente en caso de echo -e "\n Hello!", bash no hace nada, e -einterpreta \ncomo una nueva línea. pero en la primera situación mencionada, el proceso de interpretación se realizó antes \nde ser interpretado. ¿Podría explicar eso por favor?
Mohammed Noureldin
1
Ok, culpa mía, he estado leyendo sobre eso durante 2 días con sus noches, por lo tanto, aparentemente comencé a mezclar los casos, creo que obtuve algo más sedque me confundió anoche (tal vez hice algo mal ayer), pero ahora intenté de nuevo lo mismo con echo -ey sed, y obtuve lo mismo que exceptuado, ¡gracias!
Mohammed Noureldin