Qual è il contrario di echo -e?


13

Se ho una stringa con caratteri non stampabili, nuove linee o schede, c'è un modo che posso usare echoper stampare questa stringa e mostrare i codici per questi caratteri (ad esempio, \nper la nuova riga, \bper il backspace)?


2
puoi usare il comando printf, vedi man printf
PersianGulf

12
e- ohce* rimshot *
David Richerby,

3
printf '%q' "$str"stamperà la stringa salvata. Non sto aggiungendo questo come una risposta poiché non è la stessa forma di fuga che echo -eutilizza - piuttosto, è destinato a essere eval-sicuro - ma (1) è abbastanza buono se il tuo obiettivo è la leggibilità umana, (2) è abbastanza buono se il tuo obiettivo è la generazione di shell sicura, e (3) echo -eè comunque Evil And Wrong (se leggi le specifiche POSIX, vedrai che printf è il modo preferito per eseguire la formattazione delle stringhe e echo -enon è garantito da POSIX baseline su tutti).
Charles Duffy,

Risposte:


7

Ci sono molti modi per farlo. I due più portatili che conosco sono sede odsono entrambi POSIX.

printf '\n\r\b\t\033[01;31m' | sed -n l

Gli piace ... readescape di stile - C-style.

PRODUZIONE

$
\r\b\t\033[01;31m$

od è un po 'più configurabile ...

printf '\n\r\b\t\033[01;31m' |
od -v -w12 -t c -t a -A n

 \n  \r  \b  \t 033   [   0   1   ;   3   1   m
 nl  cr  bs  ht esc   [   0   1   ;   3   1   m

Se vuoi sapere quali sono tutte queste opzioni, puoi man odspecificare, ma desidero due tipi di escape: il -t cbackslash escape e i -t acaratteri con nome. L' -wopzione utilizzata sopra non è specificata da POSIX.

Ed ecco una piccola funzione di shell che stamperà in modo portabile i valori ottali di ogni byte nei suoi argomenti - che, ovviamente, odpotrebbe gestire anche con -t o:

proctal() (LC_ALL=C
    for a do while [ -n "$a" ] 
    do printf %o\\n "'$a"
    a=${a#?}; done; done)  

È semplice. Questo è un po 'più complicato. Dovrebbe essere in grado di fare ciò che possono fare le printf -qimplementazioni specifiche della shell .

bsq() (set -f; export LC_ALL=C IFS=\'
    for a do q=${a##*\'}; printf \'
    [ -n "${a#"$q"}" ] &&
        printf "%s'\''" ${a%\'*}
    printf "%s'\n'''''\n" "$q"; done |
    sed -n "/'''''"'/!H;1h;//!d;$!n;x;l' |
    sed -e :n -e '/\\$/N;s/.\n//;tn
        s/\([^\\]\\\(\\\\\)*\)\([0-9]\)/\10\3/g
        s/\\\\'"''/\\\\''"'/g;s/$$//'
)

Usando la stringa di esempio precedente con un po 'di più:

bsq "$(printf '\n\r\'\''b\t\033[01;31m')"

PRODUZIONE

'\n\r\\'\''b\t\0033[01;31m'

È solo leggermente diverso. Potresti notare che c'è un extra 0e un extra \backslash. Questo per consentire una facile traduzione in un reado un %b printfargomento. Per esempio:

i=0
until [ $((i=$i+1)) -gt 5 ]
do touch "\%$i$(printf 'hey\b \t;\n\033 ')"
done   #just for ugly's sake

bsq * | eval "
    printf '<%b>\n' $(tr \\n \ )
" | tee /dev/fd/2 |
sed -n l

PRODUZIONE

<\%1he  ;
>
<\%2he  ;
>
<\%3he  ;
>
<\%4he  ;
>
<\%5he  ;
>
<\\%1hey\b \t;$
\033 >$
<\\%2hey\b \t;$
\033 >$
<\\%3hey\b \t;$
\033 >$
<\\%4hey\b \t;$
\033 >$
<\\%5hey\b \t;$
\033 >$

@ StéphaneChazelas Farà comunque solo caratteri a byte singolo, ma si spera che sia meno probabile che si rovini adesso.
Mikeserv,

1
Lascia che ti porti al segno dei 10k :)
Ramesh,

Woohoo !!!!!!!!!
slm

@slm - fammi indovinare .. Ti è davvero piaciuto il proctal?
Mikeserv,

@ StéphaneChazelas - hai qualche idea su bsq()- manca qualcosa? Chiedo perché non sono completamente fiducioso delle barre rovesciate.
Mikeserv,

12

Quando si rimuove l' opzione -esu echo, in bashe purché l' xpg_echoopzione non sia stata abilitata, le stringhe devono essere stampate come nient'altro che il loro testo originale. Quindi \ne \tsi presenterebbe letteralmente.

Esempio

$ echo "hi\t\tbye\n\n"
hi\t\tbye\n\n

$ echo -e "hi\t\tbye\n\n"
hi      bye

Puoi anche usare il printfcomando integrato di ksh93, zsho anche bashper finagle.

$ printf "%q\n" "$(echo -e "hi\t\tbye\n\nbye")"
$'hi\t\tbye\n\nbye'

( bashoutput mostrato sopra. Ci sono alcune variazioni a seconda della shell).

estratto dahelp printf inbash

%q citare l'argomento in un modo che può essere riutilizzato come input della shell


1
Non sta printf %qtroncando i messaggi finali \n, è la $()cattura dell'output che li elimina.
ecatmur,

@ecatmur - grazie l'ho scritto a tarda notte e non avevo provato a eseguire il debug ulteriormente. Avresti ragione, è la subshell che li sta togliendo. Ecco un motivo per cui: unix.stackexchange.com/questions/17747/…
slm

... in ogni caso, l'esecuzione printfall'interno di una subshell per catturare il suo output è sciocca, poiché printf -v varnamemetterà l'output direttamente in una variabile, senza subhell coinvolto.
Charles Duffy,

@CharlesDuffy - Non ti sto seguendo, non sto correndo printfin una subshell, stavo correndo echoin uno, puramente per dimostrare che puoi prendere l'output di caratteri speciali da echoe convertirlo nella notazione con escape.
slm

@slm, questa è stata una risposta al primo commento (beh, il codice a cui ha risposto il primo commento), non il codice come l'ho trovato ora. Se ho dedotto qualcosa di inesatto sullo stato di modifica precedente, mi scuso.
Charles Duffy,

5

Potresti usare qualcosa come

$ cat filename
Ramesh is testing
New Line        is

Ora, potresti fare qualcosa del genere,

$ cat -A filename

Produzione

Ramesh is testing$
New Line ^Iis $

Un altro test generale senza file è come,

$ echo Hello$'\t'world. | cat -A

Il comando sopra fornisce l'output come,

Hello^Iworld.$

Riferimenti


4
Oppure, in non-GNU implementazioni di gatto, per esempio MacOS / X, prendere il vostro gatto dal veterinario ... cat -vet
tink

3

Con zsh, ci sono il (q), (qq), (qqq), (qqqq)bandiere di espansione variabile in grado di citare le variabili in vari modi:

$ a=$'a b\nba\bc\u00e9\0'

$ printf '%s\n' $a
a b
bcé

$ printf %s $a | od -vtc
0000000   a       b  \n   b   a  \b   c 303 251  \0
0000013

$ printf '%s\n' ${(q)a}
a\ b$'\n'ba$'\b'cé$'\0'

$ printf '%s\n' ${(qq)a}
'a b
bcé'

$ printf '%s\n' ${(qqq)a}
"a b
bcé"

$ printf '%s\n' ${(qqqq)a}
$'a b\nba\bcé\0'

$ (){local LC_ALL=C; print -r -- ${(qqqq)a}}
$'a b\nba\bc\303\251\0'

Nel tuo caso, probabilmente vorresti uno degli ultimi due.


1

od -cstamperà normalmente caratteri normali, ma caratteri speciali (tabulazione, riga nuova, ecc.) e caratteri non stampabili come printfcodice di escape.

Così:

$ echo -e asdf\\nghjk\\003foo | od -c -An
   a   s   d   f  \n   g   h   j   k 003   f   o   o  \n

La -Andice oddi non uscita l'indirizzo.


-1

Usa il printfcomando Per esempio:

printf "Hello\nthis is my line

uscirà

Hello
this is my line

1
Questa è la stessa come echo -e, sto cercando l' inverso .
drs

mi puoi dare un esempio specifico?
Lazuardi N Putra,
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.