Perché i comandi "echo -e" non sembrano produrre l'output giusto?


21

Nel terminale di Ubuntu 18.04 LTS, quando scrivo questo comando:

echo -e "Hello\\\n"

Dà questo come output:

Hello\n

Ma dovrebbe stampare, come dice la pagina man :

Hello\

Cioè, prima stampa Hello, quindi \, quindi un carattere di nuova riga (e quindi un'altra nuova riga). Dov'è il problema?

Vedi questi pochi echo -ecomandi e il loro output :

man420@man420-X542UQ:~$ echo -e "HEllo\a\a\a\a\a\a\\\n"
HEllo\n
man420@man420-X542UQ:~$ echo -e "HEllo\\\n"
HEllo\n
man420@man420-X542UQ:~$ echo -e "HEllo\a\\\n"
HEllo\n

sì. per i primi 2 \ dovrebbe essere visualizzato un \ .e l'ultimo \ e n una fuga di barra rovesciata \ n (nuova riga) .perché dovrebbe stampare Hello \
yolin00

1
Provalo senza virgolette.
ajgringo619

2
Una risposta sorprendente è stata fornita da Eliah Kagan, che dovresti accettare.
Vanadio

2
Non utilizzare echoin primo luogo: utilizzare printf.
Chepner,

2
Usa sempre virgolette singole se vuoi essere sicuro che ciò che scrivi sia esattamente ciò che viene passato al comando come argomento.
Giacomo Alzetta,

Risposte:


29

Le barre rovesciate vengono trattate appositamente da echo -e, ma prima a volte vengono trattate specialmente dalla shell (che in questo caso lo è bash), secondo le regole di quotazione della shell .

L'argomento in echorealtà vede è Hello\\n. Poiché sei passato -ea echo, tratta in modo speciale le escape di barra rovesciata e \\viene compresso in una sola \. Il finale nnon è sfuggito, quindi appare letteralmente.

La ragione di ciò è che, prima e separatamente dal funzionamento di echose stesso, la shell tratta \specialmente in alcuni contesti ma non in altri. I \personaggi non quotati vengono sempre trattati in modo speciale, i caratteri a virgoletta singola\ non vengono mai trattati in modo speciale, ma il trattamento dei caratteri tra virgolette doppie \ , come nel comando eseguito, è più sottile e complicato.

Quando la shell incontra un testo tra virgolette in un comando, come nel caso "Hello\\\n", tratta \un carattere di escape quando precede un carattere che può avere un significato speciale tra virgolette doppie e non altrimenti .

  1. Perché a \volte ha un significato speciale dentro "", un \che precede immediatamente un altro \ha l'effetto di citare quel secondo \. Quindi all'interno delle doppie virgolette, le prime \\vengono compresse \.
  2. Dopo quei primi due \personaggi, c'è un terzo \personaggio che non è interessato da quei primi due e che precede un n. Ma nnon è un personaggio mai trattato in modo speciale tra virgolette doppie, quindi il personaggio \precedente non viene trattato in modo particolare in questa situazione. Così \nrimane \n.

L'effetto è che, tra virgolette doppie, \\\nviene interpretato come \\n.

Quando echo -evede \\n, il primo \rimuove il significato speciale dal secondo, quindi echostampa \nletteralmente per quel testo.


Se il tuo obiettivo è stampare Hellocon una nuova riga extra ma senza barre rovesciate (la domanda era inizialmente ambigua su questo, in più penso che sia un esempio utile), quindi una soluzione è rimuovere un \. Esecuzione di echo -e "Hello\\n"output Hellocon una nuova riga aggiuntiva alla fine.

Una soluzione migliore è usare virgolette singole e scrivere echo -e 'Hello\n'. Le virgolette singole sono la forma di citazione più forte. Una soluzione ancora migliore è di solito usare al printfposto di echo, che in questo caso sarebbe printf 'Hello\n\n'.

Se il tuo obiettivo è stampare Hello\includendo la barra rovesciata, seguita da una nuova riga in più , allora l'approccio tra virgolette è possibile ma ingombrante. Per capirlo, lavora all'indietro: echo -econverte \\in \e \nin una nuova riga, e la doppia virgoletta si converte \\in \, quindi puoi farlo con sei barre rovesciate ( echo -e "Hello\\\\\\n"), perché \\nsi trasforma in \nuna barra rovesciata che sfugge a un'altra. Puoi anche farlo con cinque, perché la doppia virgoletta viene mantenuta \nquando \non è stato eseguito l'escaping.

Questo illustra il vantaggio di echo -evirgolette singole: inserisci semplicemente quello che vuoi vedere tra virgolette singole ( echo -e 'Hello\\\n'). printfva bene anche qui. Un'opzione è printf 'Hello\\\n\n'. Ma dove printfbrilla davvero è che puoi inserire argomenti aggiuntivi. Puoi usare printf '%s\n\n' 'Hello\', che inserisce il secondo argomento (letteralmente Hello\perché le virgolette singole non cambiano nulla) al posto di %s.

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.