Caratteri della scheda Eco nello script bash


313

Come faccio ad echo uno o più caratteri di tabulazione usando uno script bash? Quando eseguo questo codice

res='       'x # res = "\t\tx"
echo '['$res']' # expect [\t\tx]

Capisco questo

res=[ x] # that is [<space>x]

Risposte:


529
echo -e ' \t '

farà eco a "spazio tab spazio newline" ( -esignifica "abilita l'interpretazione di backslash escape"):

$ echo -e ' \t ' | hexdump -C
00000000  20 09 20 0a                                       | . .|

Grazie Johannes. Mi hai aiutato a trovare questa soluzione: res = '\ t \ t'x; echo -e '[' $ res ']'
kalyanji

2
Ti capita di sapere, perché echo -enon funziona da Makefiles?
dma_k,

23
Questo perché echo -enon è POSIX e le makechiamate /bin/shche normalmente non sono utilizzate dal programma vengono utilizzate in modo interattivo e normalmente non sono state -eimplementate. Per la portabilità, utilizzare printf '\t'invece.
Jo So,

In Darwin (macOS), la manpagina per il echocomando non menziona l'opzione -e. Tuttavia, questa opzione è accettata.
ePi272314,

75

Usa printf, no echo.

Esistono diverse versioni del echocomando. C'è /bin/echo(che può essere o meno la versione GNU Coreutils, a seconda del sistema), e il echocomando è integrato nella maggior parte delle shell. Versioni diverse hanno modi diversi (o in nessun modo) di specificare o disabilitare le escape per i caratteri di controllo.

printfd'altra parte, ha molte meno variazioni. Può esistere come comando, in genere /bin/printf, ed è incorporato in alcune shell (bash e zsh ce l'hanno, tcsh e ksh no), ma le varie versioni sono molto più simili tra loro rispetto alle diverse versioni di echo. E non c'è bisogno di ricordare le opzioni della riga di comando (con alcune eccezioni; GNU Coreutils printf accetta --versione --help, e il built-in bash printf accetta -v varper memorizzare l'output in una variabile).

Per il tuo esempio:

res='           'x # res = "\t\tx"
printf '%s\n' "[$res]"

E ora è tempo per me di ammettere che echofunzionerà altrettanto bene per l'esempio di cui stai chiedendo; devi solo mettere doppie virgolette attorno all'argomento:

echo "[$res]"

come ha scritto kmkaplan (due anni e mezzo fa, l'ho appena notato!). Il problema con i tuoi comandi originali:

res='           'x # res = "\t\tx"
echo '['$res']' # expect [\t\tx]

non è con echo; è che la shell ha sostituito la scheda con uno spazio echomai visto prima.

echova bene per output semplice, come echo hello world, ma dovresti usare printfogni volta che vuoi fare qualcosa di più complesso. È possibile ottenere echoal lavoro, ma il codice risultante rischia di fallire quando si esegue con una diversa echoimplementazione o di una shell diversa.


1
Mi è piaciuto questo, mi permette di usare la conoscenza di printf e di tutti gli identificatori di formato.
Arun,

@JezenThomas: non è più votato perché risponde alla domanda in un modo diverso da quello richiesto. La domanda menziona specificamente l'eco e l'eco non è un verbo ma un comando.
Paulo Neves,

@PauloNeves: Direi che è usato come un verbo nella domanda: "Come faccio ad echo uno o più caratteri di tabulazione usando uno script bash?"
Keith Thompson,

34

Inserisci la stringa tra virgolette doppie :

echo "[$res]"

1
lo stesso qui - questo è quello che ho provato prima. - ha funzionato benissimo
froderik il

2
@kmkaplan Funziona per me in zsh - fallisce per me in bash
Kal

34

Puoi anche provare:

echo Hello$'\t'world.

4
+1 per una soluzione più generale. Uso bash da anni e l'ho appena imparato!
Aryeh Leib Taurog,

Questa è una risposta molto più generale della risposta accettata in quanto può essere utilizzata senza eco.
Jwan,


16

Dalla pagina man di bash:

Le parole del modulo $ 'stringa' sono trattate in modo speciale. La parola si espande in stringa, con i caratteri con escape backslash sostituiti come specificato dallo standard ANSI C.

Quindi puoi farlo:

echo $'hello\tworld'

Perché questo funziona sul cli ma non in uno script bash?
Freek,

13

Utilizzare la Verbatim battitura, ^V( CTRL+V, C-v, qualunque cosa ).

Quando si digita ^Vnel terminale (o nella maggior parte degli editor Unix), il seguente carattere viene preso alla lettera . Puoi usarlo per digitare un carattere di tabulazione letterale all'interno di una stringa che stai facendo eco.

Qualcosa come i seguenti lavori:

echo "^V<tab>"     # CTRL+V, TAB

Documenti Bash ( qv , "quoted-insert")

quoted-insert (Cq, Cv) Aggiunge il carattere successivo che digiti alla riga alla lettera. Ecco come inserire sequenze di tasti come Cq, ad esempio.

nota a margine: secondo questo, ALT+TAB dovrebbe fare la stessa cosa, ma tutti abbiamo legato quella sequenza al cambio di finestra, quindi non possiamo usarla

tab-insert (M-TAB) Inserisce un carattere tab.

-

Nota: puoi usare questa strategia con tutti i tipi di personaggi insoliti. Come un ritorno in carrozza:

echo "^V^M"        # CTRL+V, CTRL+M

Questo perché il ritorno a capo è ASCII 13 e M è la 13a lettera dell'alfabeto, quindi quando si digita ^M, si ottiene il 13 ° carattere ASCII. Puoi vederlo in azione usando ls^M, a un prompt vuoto, che inserirà un ritorno a capo, facendo sì che il prompt si comporti proprio come hai premuto return. Quando questi personaggi vengono normalmente interpretati, letteralmente ottieni il carattere letterale.


1
Vorrei poterti dare più voti per questo. In questo caso non volevo usare un -e nei miei argomenti, e questo funziona alla grande. Grazie!
Aaron R.,

"... la maggior parte dei redattori Unix"? Ho provato ad entrare in questo sia con vi che con emacs e non ha dato i risultati desiderati in entrambi.
GreenMatt,

È davvero fantastico! E mi ha salvato la giornata quando ho provato a usarlo grepper catturare linee contenenti tabpersonaggi.
Joël,


2

Se si desidera utilizzare echo "a\tb"in uno script, si esegue lo script come:

# sh -e myscript.sh

In alternativa, puoi dare a myscript.sh l'autorizzazione all'esecuzione e quindi eseguire lo script.

# chmod +x myscript.sh
# ./myscript.sh

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.