Was ist die Umkehrung von Echo-e?

13

Wenn ich eine Zeichenfolge mit nicht druckbaren Zeichen, neuen Zeilen oder Tabulatoren habe, gibt es eine Möglichkeit echo, diese Zeichenfolge zu drucken und Codes für diese Zeichen anzuzeigen (z. B. \nfür neue Zeilen, \bfür die Rücktaste)?

drs
quelle
2
Sie können den Befehl printf verwenden, siehe man printf
PersianGulf
12
e- ohce* rimshot *
David Richerby
3
printf '%q' "$str"druckt die entkoppelte Zeichenfolge. Ich füge dies nicht als Antwort hinzu, da es nicht die gleiche Form des Fluchtens ist, die echo -everwendet wird - es soll vielmehr auswertungssicher sein -, aber (1) es ist gut genug, wenn Ihr Ziel die menschliche Lesbarkeit ist, (2) es ist Gut genug, wenn Ihr Ziel die sichere Shell-Generierung ist und (3) auf echo -ejeden Fall Evil And Wrong ist (wenn Sie die POSIX-Spezifikation lesen, werden Sie feststellen, dass printf die bevorzugte Methode für die Formatierung von Zeichenfolgen ist und echo -evon POSIX unter nicht garantiert wird alle).
Charles Duffy

Antworten:

7

Es gibt viele Möglichkeiten, dies zu tun. Die tragbarsten zwei, die ich kenne, sind sedund od- sie sind beide POSIX.

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

Es mag ... readStil entkommt - C-Stil.

AUSGABE

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

od ist etwas konfigurierbarer ...

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

Wenn Sie wissen man odmöchten , welche dieser Optionen Sie verwenden können, geben Sie an , dass Sie zwei Arten von Escape- Zeichen verwenden möchten: das -t cBackslash-Escape- -t aZeichen und die benannten Zeichen. Die -woben verwendete Option ist nicht POSIX-spezifiert.

Und hier ist eine kleine Shell-Funktion, die portabel die Oktalwerte jedes Bytes in seinen Argumenten ausgibt - was natürlich auch mit odFolgendem umgehen könnte -t o:

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

Das ist ganz einfach. Das ist etwas komplizierter. Es sollte jedoch in der Lage sein, das zu tun, was die Shell-spezifischen printf -qImplementierungen können.

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/$$//'
)

Beispielstring von früher mit ein wenig zusätzlichem verwenden:

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

AUSGABE

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

Es ist nur ein bisschen anders. Sie werden vielleicht feststellen, dass es einen zusätzlichen 0und einen zusätzlichen \bSchrägstrich gibt. Dies soll eine einfache Übersetzung in ein readoder mehrere %b printfArgumente ermöglichen. Beispielsweise:

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

AUSGABE

<\%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 >$
mikeserv
quelle
@ StéphaneChazelas Es wird immer noch nur Einzelbyte-Zeichen geben, aber es ist hoffentlich weniger wahrscheinlich, dass es jetzt schief geht.
mikeserv
1
Lassen Sie mich Sie auf die 10-km-Marke bringen :)
Ramesh
Woohoo !!!!!!!!!
SLM
@slm - lass mich raten .. Dir hat das wirklich gefallen proctal?
mikeserv
@ StéphaneChazelas - hast du irgendwelche Gedanken darüber bsq()- fehlt etwas? Ich frage, weil ich nicht ganz sicher bin, was die Backslashes angeht.
mikeserv
12

Wenn Sie den -eSchalter auf echo, in bashund entfernen , sofern die xpg_echoOption nicht aktiviert wurde, sollten die Zeichenfolgen nur als Originaltext gedruckt werden. Also \nund \twürde sich so buchstäblich zeigen.

Beispiel

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

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

Sie können auch die Verwendung printfintegrierten Befehl von ksh93, zshoder bashdies auch finagle.

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

( bashAusgabe wie oben gezeigt. Je nach Shell gibt es einige Abweichungen.)

Auszug aushelp printf inbash

%q Zitieren Sie das Argument so, dass es als Shell-Eingabe wiederverwendet werden kann

slm
quelle
1
Es ist nicht printf %qdas Abschneiden der abschließenden \ns, sondern die $()Ausgabeerfassung, die sie entfernt.
Ecatmur
@ecatmur - danke, ich schrieb so spät in der Nacht und hatte nicht versucht, es weiter zu debuggen. Sie hätten Recht, es ist die Unterschale, die sie auszieht. Hier ist ein Grund warum: unix.stackexchange.com/questions/17747/…
slm
... auf printfjeden Fall ist es dumm, in einer Subshell zu laufen, um deren Ausgabe zu erfassen, da printf -v varnamedie Ausgabe direkt in eine Variable verschoben wird, ohne dass eine Subshell betroffen ist.
Charles Duffy
@CharlesDuffy - Ich verfolge Sie nicht, ich bin nicht printfin einer Subshell aktiv, ich war echoin einer aktiv, nur um zu demonstrieren, dass Sie die Sonderzeichenausgabe von echound zurück in die maskierte Notation konvertieren können.
slm
@slm, das war eine Antwort auf den ersten Kommentar (also auf den Code, auf den der erste Kommentar geantwortet hat), nicht auf den Code, wie ich ihn jetzt gefunden habe. Wenn ich auf etwas Ungenaues über den vorherigen Bearbeitungsstatus schließe, entschuldige ich mich.
Charles Duffy
5

Sie könnten etwas verwenden,

$ cat filename
Ramesh is testing
New Line        is

Nun könnten Sie so etwas tun,

$ cat -A filename

Ausgabe

Ramesh is testing$
New Line ^Iis $

Ein weiteres allgemeines Testen ohne Dateien ist wie folgt:

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

Der obige Befehl liefert die Ausgabe als

Hello^Iworld.$

Verweise

Ramesh
quelle
4
Oder bringen Sie Ihre Katze in Nicht-GNU-Implementierungen von cat, z. B. MacOS / X, zum Tierarzt ... cat -vet
tink
3

Mit zshgibt es die (q), (qq), (qqq), (qqqq)variable Expansion Flags, die können zitieren die Variablen auf verschiedene Weise:

$ 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'

In Ihrem Fall möchten Sie wahrscheinlich eine der letzten beiden.

Stéphane Chazelas
quelle
1

od -cNormalerweise werden normale Zeichen gedruckt, Sonderzeichen (Tabulator, Zeilenvorschub usw.) und nicht druckbare Zeichen als printfEscape-Code.

So:

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

Das -Ansagt od, die Adresse nicht auszugeben.

Brian Minton
quelle
-1

Verwenden Sie den printfBefehl. Beispielsweise:

printf "Hello\nthis is my line

wird ausgegeben

Hello
this is my line
Lazuardi N Putra
quelle
1
Das ist das gleiche wie echo -e, ich suche das Gegenteil .
drs
Kannst du mir ein konkretes Beispiel geben?
Lazuardi N Putra