Echo-Tab-Zeichen im Bash-Skript

313

Wie kann ich ein oder mehrere Tabulatorzeichen mithilfe eines Bash-Skripts wiedergeben? Wenn ich diesen Code ausführe

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

Ich verstehe das

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

Antworten:

529
echo -e ' \t '

gibt 'Leerzeichen Tab Leerzeichen Zeilenumbruch' aus ( -ebedeutet 'Interpretation von Backslash- Escapezeichen aktivieren'):

$ echo -e ' \t ' | hexdump -C
00000000  20 09 20 0a                                       | . .|
Johannes Weiss
quelle
Danke Johannes. Sie haben mir geholfen, diese Lösung zu finden: res = '\ t \ t'x; echo -e '[' $ res ']'
kalyanji
2
Weißt du zufällig, warum echo -efunktioniert das nicht mit Makefiles?
dma_k
23
Das echo -eliegt daran, dass nicht POSIX und makeAufrufe, /bin/shdie normalerweise nicht vom Programm verwendet werden, interaktiv verwendet werden und normalerweise nicht -eimplementiert sind. Verwenden Sie printf '\t'stattdessen für die Portabilität .
Jo So
In Darwin (macOS) wird die Option auf der manSeite für den echoBefehl nicht erwähnt -e. Diese Option wird jedoch akzeptiert.
ePi272314
75

Verwenden Sie printfnicht echo.

Es gibt mehrere verschiedene Versionen des echoBefehls. Es gibt /bin/echo(je nach System kann es sich um die GNU Coreutils-Version handeln oder nicht), und der echoBefehl ist in die meisten Shells integriert. Verschiedene Versionen haben unterschiedliche Möglichkeiten (oder keine Möglichkeit), Escapezeichen für Steuerzeichen anzugeben oder zu deaktivieren.

printfhat andererseits viel weniger Variation. Es kann normalerweise als Befehl existieren /bin/printfund ist in einige Shells integriert (bash und zsh haben es, tcsh und ksh nicht), aber die verschiedenen Versionen sind einander viel ähnlicher als die verschiedenen Versionen von echo. Und Sie müssen sich keine Befehlszeilenoptionen merken (mit wenigen Ausnahmen; GNU Coreutils printf akzeptiert --versionund --help, und die integrierte Bash printf akzeptiert -v var, um die Ausgabe in einer Variablen zu speichern).

Für Ihr Beispiel:

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

Und jetzt ist es Zeit für mich zuzugeben, dass dies echofür das Beispiel, nach dem Sie fragen, genauso gut funktioniert. Sie müssen nur doppelte Anführungszeichen um das Argument setzen:

echo "[$res]"

wie kmkaplan schrieb (vor zweieinhalb Jahren habe ich es gerade bemerkt!). Das Problem mit Ihren ursprünglichen Befehlen:

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

ist nicht mit echo; Es ist so, dass die Shell die Lasche durch ein Leerzeichen ersetzt hat, bevor sie echojemals gesehen wurde.

echoist in Ordnung für einfache Ausgabe, wie echo hello world, aber Sie sollten verwenden, printfwann immer Sie etwas komplexeres tun möchten. Sie können sich echoan die Arbeit machen, aber der resultierende Code schlägt wahrscheinlich fehl, wenn Sie ihn mit einer anderen echoImplementierung oder einer anderen Shell ausführen .

Keith Thompson
quelle
1
Ich mochte dieses, es erlaubt mir, das Wissen von printf und allen Formatspezifizierern zu nutzen.
Arun
@JezenThomas: Es ist nicht mehr positiv bewertet, weil es die Frage auf eine andere Weise als gewünscht beantwortet. Die Frage erwähnt speziell Echo, und Echo ist kein Verb, sondern ein Befehl.
Paulo Neves
@PauloNeves: Ich würde sagen , es als Verb in der Frage verwendet wird : „Wie kann ich echo eines oder mehr Tabulator einen Bash - Skript?“
Keith Thompson
34

Setzen Sie Ihre Zeichenfolge zwischen doppelte Anführungszeichen:

echo "[$res]"
kmkaplan
quelle
1
das gleiche hier - das habe ich zuerst versucht. -e hat gut funktioniert
froderik
2
@kmkaplan Funktioniert für mich in zsh - scheitert für mich in Bash
Kal
34

Sie können auch versuchen:

echo Hello$'\t'world.
jbatista
quelle
4
+1 für eine allgemeinere Lösung. Ich benutze Bash seit Jahren und habe das gerade erst gelernt!
Aryeh Leib Taurog
Dies ist viel allgemeiner als die akzeptierte Antwort, da sie ohne Echo verwendet werden kann.
Jwan
22

Sie müssen das Flag -e für das Echo verwenden, dann können Sie

echo -e "\t\t x"
Lernen
quelle
16

Von der Bash-Manpage:

Wörter der Form $ 'string' werden speziell behandelt. Das Wort wird zu Zeichenfolge erweitert, wobei Zeichen mit Backslash-Escapezeichen gemäß ANSI C-Standard ersetzt werden.

So können Sie Folgendes tun:

echo $'hello\tworld'
Esoriano
quelle
Warum funktioniert das auf der CLI, aber nicht in einem Bash-Skript?
Freek
13

Verwenden Sie den wörtlich Tastendruck, ^V( CTRL+V, C-v, was auch immer ).

Wenn Sie ^Vin das Terminal (oder in den meisten Unix-Editoren) eingeben, wird das folgende Zeichen wörtlich genommen . Sie können dies verwenden, um ein Literal-Tabulatorzeichen in eine Zeichenfolge einzugeben, die Sie wiedergeben.

So etwas funktioniert wie folgt:

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

Bash-Dokumente ( siehe "Quoted-Insert")

Anführungszeichen (Cq, Cv) Fügen Sie das nächste Zeichen, das Sie eingeben, wörtlich in die Zeile ein. So fügen Sie beispielsweise Schlüsselsequenzen wie Cq ein.

Randnotiz: Demnach ALT+TAB sollte man dasselbe tun, aber wir haben alle diese Sequenz an das Umschalten des Fensters gebunden, damit wir sie nicht verwenden können

Tabulator einfügen (M-TAB) Fügen Sie ein Tabulatorzeichen ein.

- -

Hinweis: Sie können diese Strategie mit allen möglichen ungewöhnlichen Charakteren verwenden. Wie ein Wagenrücklauf:

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

Dies liegt daran, dass der Wagenrücklauf ASCII 13 ist und M der 13. Buchstabe des Alphabets ist. Wenn Sie also eingeben ^M, erhalten Sie das 13. ASCII-Zeichen. Sie können es in Aktion sehen, indem Sie ls^Man einer leeren Eingabeaufforderung einen Wagenrücklauf einfügen, wodurch die Eingabeaufforderung so funktioniert, als würden Sie die Eingabetaste drücken. Wenn diese Zeichen normalerweise interpretiert werden, wörtlich bekommt man den wörtlichen Charakter bekommen.

reiches remer
quelle
1
Ich wünschte, ich könnte Ihnen mehr Upvotes für diesen geben. Ich wollte in diesem Fall kein -e in meinen Argumenten verwenden, und das funktioniert großartig. Vielen Dank!
Aaron R.
"... die meisten Unix-Editoren"? Es wurde versucht, dies sowohl mit vi als auch mit emacs einzugeben, und es wurden auch nicht die gewünschten Ergebnisse erzielt.
GreenMatt
Das ist soooo cool! Und mir den Tag gerettet, als ich versuchte, grepZeilen mit tabZeichen zu fangen .
Joël
11

Die Verwendung von Echo zum Drucken von Variablenwerten ist eine häufige Gefahr für Bash. Referenzlink:

http://mywiki.wooledge.org/BashPitfalls#echo_.24foo

Anonym
quelle
Cool, ich mag die "BashPitfalls", ein großartiges Stück Material und lindere viel Schmerz von meiner täglichen Arbeit!
Jerry Tian
+1 weil das sooo wahr ist. Beachten Sie jedoch, dass die Kalyanji-Zeichenfolge mit einem "[" beginnt und kein "\" enthält.
kmkaplan
2

Wenn Sie echo "a\tb"in einem Skript verwenden möchten , führen Sie das Skript wie folgt aus:

# sh -e myscript.sh

Alternativ können Sie myscript.sh die Ausführungsberechtigung erteilen und dann das Skript ausführen.

# chmod +x myscript.sh
# ./myscript.sh
ATC
quelle
0
res="\t\tx"
echo -e "[${res}]"
Yanghaogn
quelle