Perché `echo -e“ \\\ SOME_TEXT ”` mostra solo una barra rovesciata?


19

Qualcuno potrebbe spiegare cosa sta succedendo dietro le quinte nella fuga di caratteri nella shell di Linux? Ho provato quanto segue e ho cercato su Google molto, senza alcun successo nel capire cosa (e come) sta succedendo:

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!

Mi sono completamente perso lì, quindi per esempio, perché tre barre rovesciate danno solo una barra rovesciata? Mi aspetterei: i primi due saranno salvati in uno, il terzo non troverà nulla per sfuggire, quindi rimarrà una barra (linea nel primo esperimento), ma ciò che sta accadendo è che il terzo è semplicemente scompare.
Perché ricevo una barra rovesciata da quattro \\\\ Hello? Mi aspetto che ogni coppia dia una barra rovesciata -> due barre rovesciate.

E perché ho bisogno di tre barre rovesciate nell'ultimo caso per sfuggire a \ n? cosa sta succedendo in background di fuga per ottenerlo? e in cosa differisce dal \\ncaso?

Apprezzo qualsiasi spiegazione di ciò che sta succedendo nelle righe precedenti.


echo -eil comportamento non è definito in alcun modo dagli standard - vedi pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html . L'output è completamente definito dall'implementazione se c'è un backslash letterale in qualsiasi punto degli input e l'unica opzione consentita è -n(il che significa che un'implementazione conforme agli standard avrà echo -estampa -esul suo output).
Charles Duffy,

... anche se sei sicuro al 100% che la tua shell sia bash, anche in questo caso echo -e non è sicura: echosi comporterà secondo lo standard se entrambe le opzioni di runtime posixe xpg_echosono abilitate, o se compilate con opzioni equivalenti di build-time. La pratica sicura è usare printfinvece - vedi le sezioni APPLICAZIONE UTILIZZO e MOTIVAZIONE del link sopra che descrive come printfagire per sostituire echo.
Charles Duffy,

Risposte:


28

Questo perché bashe echo -ecombinato. A partire dalman 1 bash

Una barra rovesciata non quotata ( \) è il carattere di escape. Conserva il valore letterale del personaggio successivo che segue, ad eccezione di <newline>. [...]

Racchiudere caratteri tra virgolette conserva il valore letterale di tutti i caratteri all'interno delle virgolette, ad eccezione di $, `, \, [...] Il backslash mantiene il suo significato speciale solo quando seguito da uno dei seguenti caratteri: $,`, ", \, o <newline>.

Il punto è: la barra rovesciata tra virgolette non è sempre speciale.

Ci sono varie implementazioni di echoin generale, è incorporato bash; l'importante qui è questo comportamento:

Se -eè attivo, vengono riconosciute le seguenti sequenze:
\\
barra rovesciata
[…]
\n
nuova riga

Ora possiamo decodificare:

  1. echo -e "\ Hello!"- niente di speciale bash, niente di speciale echo; \soggiorni.
  2. echo -e "\\ Hello!"- il primo \dice bashdi trattare \letteralmente il secondo ; echoottiene \ Hello!e agisce come sopra.
  3. echo -e "\\\ Hello!"- il primo \dice bashdi trattare \letteralmente il secondo ; echoottiene \\ Hello!e (a causa di -e) riconosce \\come \.
  4. echo -e "\\\\ Hello!"- il primo \dice bashdi trattare \letteralmente il secondo ; il terzo dice lo stesso del quarto; echoottiene \\ Hello!e (a causa di -e) riconosce \\come \.
  5. echo -e "\\\\\ Hello!"- il primo \dice bashdi trattare \letteralmente il secondo ; il terzo dice lo stesso del quarto; l'ultimo non è speciale; echoottiene \\\ Hello!e (a causa di -e) riconosce l'iniziale \\come \, l'ultimo \rimane intatto.

E così via. Come puoi vedere, fino a quattro barre rovesciate consecutive ne danno una. Ecco perché hai bisogno di (almeno) nove di loro per ottenerne tre. 9 = 4 + 4 + 1.

Ora con \n:

  1. echo -e "\n Hello!"- Non c'è niente di speciale in bash, echo ottiene la stessa stringa e (a causa di -e) interpreta \ncome una nuova riga.
  2. echo -e "\\n Hello!"- bashinterpreta \\come \; echoottiene \n Hello!e il risultato è lo stesso di cui sopra.
  3. echo -e "\\\n Hello!"- bashinterpreta l'iniziale \\come \; echoottiene \\n Hello!e (a causa di -e) interpreta \\come un letterale \che deve essere stampato.

I risultati sarebbero diversi con 'anziché "(a causa di bashcomportamenti diversi ) o senza -e( echocomportamento diverso ).


1
Grazie mille! Quindi ci sono due passi di fuga, il passo fatto da bash, e il secondo da -egiudici il testo già giudicato da bash, giusto? se è corretto, ciò rimuove la confusione. Potresti forse menzionare come si sedcomporta? ha una propria tecnica di fuga? quindi voglio dire si comporta come eco con -e?
Mohammed Noureldin,

2
@MohammedNoureldin Sì, ci sono due passaggi. La tua domanda originale va bene così com'è, non facciamola complicata sed. Tuttavia, potresti fare un'altra domanda ( sedsolo riguardo ), prima fai solo le tue ricerche.
Kamil Maciorowski,

3
@MohammedNoureldin sedseguirà gli stessi principi di base: bash interpreterà la riga di comando secondo le sue regole, analizzando (e forse rimuovendo) citazioni e escape. Il risultato di ciò viene passato a sed, che lo interpreta secondo le sue regole di fuga. A proposito, puoi semplificarlo usando una stringa tra virgolette singole bash, dal momento che non ha fatto l'interpretazione di escape eny (con bash) - bash rimuove le virgolette singole e passa ciò che è al loro interno direttamente al comando.
Gordon Davisson,

Ho ancora un piccolo problema nel echo -e "\\\n Hello!"caso. Qui bash scapperà e diventerà \\n, quindi -esfuggirà alle due barre rovesciate risultanti \\ne poi diventeranno \n. ora chi interpreta \nper farne una nuova linea? Normalmente in caso di echo -e "\n Hello!", bash non fa nulla e -einterpreta \ncome nuova riga. ma nella prima menzionata situazione il processo di interpretazione è stato fatto prima \ndi essere interpretato. Potresti spiegarlo per favore?
Mohammed Noureldin,

1
Ok, colpa mia, ne ho letto per 2 giorni con le loro notti, quindi a quanto pare ho iniziato a mescolare i casi, credo di avere qualcos'altro in sedcui mi hai confuso la scorsa notte (forse ho fatto qualcosa di sbagliato ieri), ma ora ho ho provato di nuovo lo stesso con echo -ee sed, e ho ottenuto la stessa cosa di tranne, grazie!
Mohammed Noureldin,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.