Ich habe gehört, das printf
ist besser als echo
. Ich kann mich aus meiner Erfahrung nur an eine Instanz erinnern, die ich verwenden musste, printf
weil echo
sie nicht zum Einfügen von Text in ein Programm unter RHEL 5.8 printf
funktioniert hat, sondern . Aber anscheinend gibt es andere Unterschiede, und ich möchte nachfragen, was sie sind und ob es bestimmte Fälle gibt, in denen man einen gegen den anderen verwendet.
text-processing
echo
printf
amphibient
quelle
quelle
echo -e
?echo -e
funktioniert nicht insh
, nur inbash
(aus irgendeinem Grund), und Docker verwendet beispielsweisesh
standardmäßig für seineRUN
Befehleecho -e
für mich im Android Terminal, was im Wesentlichen istsh
.Antworten:
Grundsätzlich handelt es sich um eine Frage der Portabilität (und Zuverlässigkeit).
Anfangs
echo
habe ich keine Option akzeptiert und nichts erweitert. Alles, was es tat, war die Ausgabe seiner Argumente, die durch ein Leerzeichen getrennt und durch ein Zeilenvorschubzeichen abgeschlossen wurden.Nun dachte jemand, es wäre schön, wenn wir Dinge tun könnten, um
echo "\n\t"
Zeilenvorschub- oder Tabulatorzeichen auszugeben oder die Option zu haben, das abschließende Zeilenvorschubzeichen nicht auszugeben.Sie dachten dann viel genauer nach, fügten diese Funktionalität jedoch nicht der Shell hinzu (beispielsweise,
perl
wenn in doppelten Anführungszeichen\t
ein Tabulatorzeichen steht)echo
.David Korn realisiert den Fehler und stellte eine neue Form der Schale Zitate:
$'...'
die durch später kopiert wurdebash
undzsh
aber es war viel zu spät von dieser Zeit.Wenn nun ein Standard-UNIX
echo
ein Argument empfängt, das die beiden Zeichen enthält,\
undt
statt sie auszugeben, gibt es ein Tabulatorzeichen aus. Und sobald\c
ein Argument angezeigt wird, wird die Ausgabe gestoppt (sodass auch die nachgestellte Zeile nicht ausgegeben wird).Andere Shells / Unix-Anbieter / -Versionen haben sich für eine andere Vorgehensweise entschieden: Sie haben eine
-e
Option zum Erweitern von Escape-Sequenzen und eine-n
Option hinzugefügt , mit der die nachgestellte Zeile nicht ausgegeben wird. Einige müssen-E
Escape-Sequenzen deaktivieren, andere-n
jedoch nicht-e
. Die Liste der von einerecho
Implementierung unterstützten Escape-Sequenzen muss nicht mit der Liste der von einer anderen Implementierung unterstützten identisch sein.Sven Mascheck hat eine schöne Seite, die das Ausmaß des Problems zeigt .
Bei
echo
Implementierungen, die Optionen unterstützen, gibt es im Allgemeinen keine Unterstützung für a--
, um das Ende von Optionen zu markieren (echo
dies ist bei einigen nicht Bourne-ähnlichen Shells der Fall, und zsh unterstützt dies-
jedoch). Daher ist es beispielsweise schwierig,"-n"
mitecho
in auszugeben viele Muscheln.Bei einigen Shells wie
bash
¹ oderksh93
² oderyash
($ECHO_STYLE
variabel) hängt das Verhalten sogar davon ab, wie die Shell kompiliert wurde oder von der Umgebung (das Verhalten von GNUecho
ändert sich auch, wenn$POSIXLY_CORRECT
es sich in der Umgebung befindet und mit der Version 4 ,zsh
mit derbsd_echo
Option, einige pdksh-basierte mit ihrerposix
Option oder ob sie als genannt werdensh
oder nicht). Es ist also nicht garantiert, dass sich zweibash
echo
s, auch von derselben Version vonbash
, gleich verhalten.POSIX sagt: Wenn das erste Argument
-n
Backslashes enthält, ist das Verhalten nicht spezifiziert .bash
Echo in dieser Hinsicht ist nicht POSIX, dh esecho -e
wird nicht so ausgegeben,-e<newline>
wie es POSIX erfordert. Die UNIX-Spezifikation ist strenger, sie verbietet-n
und erfordert die Erweiterung einiger Escape-Sequenzen, einschließlich\c
derjenigen, um die Ausgabe zu stoppen.Diese Spezifikationen können hier nicht wirklich Abhilfe schaffen, da viele Implementierungen nicht konform sind. Sogar einige zertifizierte Systeme wie MacOS 5 sind nicht kompatibel.
Um die aktuelle Realität wirklich darzustellen, sollte POSIX tatsächlich sagen : Wenn das erste Argument mit dem
^-([eEn]*|-help|-version)$
erweiterten regulären Ausdruck übereinstimmt oder ein Argument umgekehrte Schrägstriche enthält (oder Zeichen, deren Codierung die Codierung des umgekehrten Schrägstrichs enthält, wieα
in Gebietsschemas unter Verwendung des BIG5-Zeichensatzes), ist das Verhalten wie folgt nicht spezifiziert.Alles in allem wissen Sie nicht, was
echo "$var"
ausgegeben wird, es sei denn, Sie können sicherstellen, dass$var
die Ausgabe keine Backslash-Zeichen enthält und nicht mit beginnt-
. Die POSIX-Spezifikation sagt uns tatsächlich, dass wirprintf
in diesem Fall stattdessen verwenden sollen.Das bedeutet also, dass Sie keine
echo
unkontrollierten Daten anzeigen können. Mit anderen Worten, wenn Sie ein Skript schreiben und externe Eingaben (vom Benutzer als Argumente oder Dateinamen aus dem Dateisystem ...) verwendet werden, können Sie es nichtecho
zum Anzeigen verwenden.Das ist in Ordnung:
Das ist nicht:
(Obwohl es bei einigen (nicht UNIX-kompatiblen)
echo
Implementierungen wiebash
's einwandfrei funktioniert , wenn diexpg_echo
Option nicht auf die eine oder andere Weise aktiviert wurde, wie zum Zeitpunkt der Kompilierung oder über die Umgebung).file=$(echo "$var" | tr ' ' _)
nicht OK in den meisten Implementierungen ist (Ausnahmen sindyash
mitECHO_STYLE=raw
(mit dem Vorbehalt , dassyash
‚s Variablen nicht beliebige Sequenzen von Bytes so nicht willkürlich Dateinamen) und halten kannzsh
s‘echo -E - "$var"
6 ).printf
Andererseits ist es zuverlässiger, zumindest wenn es auf die grundlegende Verwendung von beschränkt istecho
.$var
Gibt den Inhalt von gefolgt von einem Newline-Zeichen aus, unabhängig davon, welches Zeichen es enthalten darf.Gibt es ohne das nachfolgende Zeilenumbruchzeichen aus.
Nun gibt es auch Unterschiede zwischen den
printf
Implementierungen. Es gibt einen Kern von Funktionen, die von POSIX spezifiziert werden, aber es gibt auch viele Erweiterungen. Einige unterstützen beispielsweise a%q
, um die Argumente in Anführungszeichen zu setzen, aber die Vorgehensweise ist von Shell zu Shell unterschiedlich. Einige unterstützen\uxxxx
Unicode-Zeichen. Das Verhalten istprintf '%10s\n' "$var"
bei Multi-Byte-Gebietsschemas unterschiedlich. Für gibt es mindestens drei verschiedene Ergebnisseprintf %b '\123'
Aber am Ende haben Sie
printf
keine Probleme , wenn Sie sich an die POSIX-Funktionen halten und nicht versuchen, etwas Besonderes daraus zu machen.Denken Sie jedoch daran, dass das erste Argument das Format ist und daher keine variablen / unkontrollierten Daten enthalten sollte.
Eine zuverlässigere
echo
kann implementiert werden mitprintf
:Die Subshell (die in den meisten Shell-Implementierungen das Erzeugen eines zusätzlichen Prozesses impliziert) kann bei Verwendung
local IFS
mit vielen Shells oder durch Schreiben wie folgt vermieden werden :Anmerkungen
1. Wie ist
bash
dasecho
Verhalten kann geändert werden.Mit
bash
zur Laufzeit gibt es zwei Dinge, die das Verhalten steuernecho
(nebenenable -n echo
oder neu zu definierenecho
als eine Funktion oder Alias): diexpg_echo
bash
Option , und obbash
im Posix - Modus.posix
Modus kann aktiviert werden, wennbash
aufgerufen wird alssh
oder wennPOSIXLY_CORRECT
in der Umgebung oder mit derposix
Option:Standardverhalten auf den meisten Systemen:
xpg_echo
Erweitert Sequenzen entsprechend den Anforderungen von UNIX:Es ehrt noch
-n
und-e
(und-E
):Mit
xpg_echo
und POSIX-Modus:Dieses Mal
bash
ist sowohl POSIX- als auch UNIX-konform. Beachten Sie, dass im POSIX-Modusbash
immer noch keine POSIX-Konformität besteht, da die Ausgabe-e
in folgenden Sprachen nicht erfolgt :Die Standardwerte für xpg_echo und Posix können mit den bei der Kompilierung definiert werden
--enable-xpg-echo-default
und--enable-strict-posix-default
Optionen zumconfigure
Skript. Dies ist in der Regel das, was neuere Versionen von OS / X tun, um sie zu erstellen/bin/sh
.Normalerweise würde dies jedoch keine Unix / Linux-Implementierung / -Distribution tun, die bei. Eigentlich stimmt das nicht, das/bin/bash
klarem Verstand wäre/bin/bash
Oracle mit Solaris 11 (in einem optionalen Paket) ausgeliefert wird--enable-xpg-echo-default
(das war in Solaris 10 nicht der Fall).2. Wie
ksh93
ist dasecho
Verhalten verändert werden.In
ksh93
, obecho
Escape - Sequenzen erweitert oder nicht und erkennt Optionen ist abhängig von dem Inhalt der$PATH
und / oder$_AST_FEATURES
Umgebungsvariablen.Wenn
$PATH
eine Komponente enthalten ist, die/5bin
oder/xpg
vor der/bin
oder/usr/bin
-Komponente enthält , verhält sie sich wie SysV / UNIX (erweitert Sequenzen, akzeptiert keine Optionen). Findet es/ucb
oder/bsd
zuerst oder enthält es$_AST_FEATURES
7UNIVERSE = ucb
, dann verhält es sich wie BSD 3 (-e
um die Erweiterung zu ermöglichen, erkennt es-n
).Die Standardeinstellung ist systemabhängig, BSD unter Debian (siehe die Ausgabe
builtin getconf; getconf UNIVERSE
in neueren Versionen von ksh93):3. BSD für Echo -e?
Der Hinweis auf BSD für den Umgang mit der
-e
Option ist hier etwas irreführend. Die meisten dieser unterschiedlichen und inkompatiblenecho
Verhaltensweisen wurden bei AT & T eingeführt:\n
,\0ooo
,\c
In Programmierwerkbank UNIX (basierend auf Unix V6) und den Rest (\b
,\r
...) in Unix System III Ref .-n
in Unix V7 (von Dennis Ritchie Ref )-e
in Unix V8 (von Dennis Ritchie Ref )-E
selbst möglicherweise ursprünglich vonbash
(CWRU / CWRU.chlog in Version 1.13.5 erwähnt, dass Brian Fox es am 18.10.1992 hinzufügte, GNUecho
kopierte es kurz darauf in sh-utils-1.8, das 10 Tage später veröffentlicht wurde)Während die
echo
builtin dessh
oder BSDs unterstützt hat ,-e
seit dem Tag , sie es in den frühen 90er Jahren mit dem Almquist Shell gestartet, die Standaloneecho
nicht Dienstprogramm bis heute nicht dort unterstützen ( FreeBSDecho
noch nicht unterstützt-e
, obwohl es tut Unterstützung-n
wie Unix V7 (und auch\c
nur am Ende des letzten Arguments).Die Handhabung
-e
wurde hinzugefügtksh93
ist ,echo
wenn in dem BSD - Universum in der ksh93r Version im Jahr 2006 veröffentlicht und kann bei der Kompilierung deaktiviert werden.4. Verhaltensänderung des GNU-Echos in 8.31
Da coreutils 8,31 (und diese begehen ), GNU
echo
erweitert nun Sequenzen durch Standard entkommen , wenn POSIXLY_CORRECT in der Umwelt ist, das Verhalten anzupassenbash -o posix -O xpg_echo
‚secho
builtin (siehe Bug - Report ).5. macOS
echo
Die meisten Versionen von macOS haben eine UNIX-Zertifizierung von der OpenGroup erhalten .
Ihr
sh
eingebautes Systemecho
ist kompatibel, da esbash
(eine sehr alte Version)xpg_echo
standardmäßig aktiviert ist, ihr eigenständigesecho
Dienstprogramm jedoch nicht.env echo -n
gibt nichts statt aus-n<newline>
,env echo '\n'
gibt\n<newline>
statt aus<newline><newline>
.Das
/bin/echo
ist der von FreeBSD , den Neuen - Zeile - Ausgang unterdrückt , wenn das erste Argumente-n
oder (seit 1995) , wenn das letzte Argument endet\c
, aber unterstützt keine andere Backslash Sequenzen von UNIX erforderlich, auch nicht\\
.6.
echo
Implementierungen, die beliebige Daten wörtlich ausgeben könnenGenau genommen könnte man auch zählen, dass FreeBSD / macOS
/bin/echo
über (nicht dieecho
eingebaute Shell ) wozsh
'secho -E - "$var"
oderyash
' sECHO_STYLE=raw echo "$var"
(printf '%s\n' "$var"
) geschrieben werden könnte:Implementierungen, die Folgendes unterstützen
-E
und-n
für die Folgendes konfiguriert werden kann:Und
zsh
'secho -nE - "$var"
(printf %s "$var"
) könnte geschrieben werden7.
_AST_FEATURES
und der ASTUNIVERSE
Das
_AST_FEATURES
ist nicht dazu gedacht, direkt manipuliert zu werden. Es wird verwendet, um AST-Konfigurationseinstellungen über die Befehlsausführung zu verbreiten. Die Konfiguration soll über die (undokumentierte)astgetconf()
API erfolgen. Im Innerenksh93
ist dasgetconf
eingebaute (mitbuiltin getconf
oder durch Aufrufen aktiviertcommand /opt/ast/bin/getconf
) die Schnittstelle zuastgetconf()
Beispielsweise müssen Sie
builtin getconf; getconf UNIVERSE = att
dieUNIVERSE
Einstellung auf ändernatt
(echo
unter anderem , um das SysV-Verhalten zu beeinflussen). Danach werden Sie feststellen, dass die$_AST_FEATURES
Umgebungsvariable enthältUNIVERSE = att
.quelle
echo
Erweiterung der\x
Sequenzen im Gegensatz zur Shell als Teil der Quotierungssyntax besteht darin, dass Sie dann ein NUL-Byte ausgeben können (ein weiteres, möglicherweise falsch definiertes Unix-Byte besteht aus durch Nullen getrennten Sequenzen) Zeichenfolgen, bei denen die Hälfte der Systemaufrufe (wieexecve()
) keine willkürlichen Folgen von Bytes annehmen kann)printf
scheint dies sogar ein Problem zu sein, da die meisten Implementierungen es falsch machen. Die einzige korrekte Implementierung, die mir bekannt ist, ist inbosh
und auf der Seite von Sven Maschek werden die Probleme mit Null-Bytes über nicht aufgelistet\0
.Möglicherweise möchten Sie
printf
für die Formatierungsoptionen verwenden.echo
ist nützlich, wenn es darum geht, den Wert einer Variablen oder einer (einfachen) Zeile zu drucken, aber das ist alles, was dazu gehört.printf
kann im Grunde das tun, was die C-Version davon kann.Anwendungsbeispiele und Funktionen:
Echo
:printf
:Quellen:
quelle
echo
Drucken einer Variablen kann fehlschlagen, wenn der Wert der Variablen Metazeichen enthält.Ein "Vorteil", wenn man es so nennen will, wäre, dass man es nicht so sagen muss
echo
, um bestimmte Escape-Sequenzen wie z\n
. Es weiß, wie man sie interpretiert, und es wird nicht erforderlich sein-e
, dies zu tun.(NB: der letzte
\n
ist notwendig,echo
impliziert es, wenn Sie die-n
Option geben)gegen
Beachten Sie die letzte
\n
inprintf
. Am Ende des Tages ist es eine Frage des Geschmacks und der Anforderungen, was Sie verwenden:echo
oderprintf
.quelle
/usr/bin/echo
und dasbash
eingebaute. Der Schalterdash
,ksh
undzsh
builtinecho
muss nicht verwendet-e
werden, um Zeichen mit umgekehrten Schrägstrichen zu erweitern.printf '%s\n' 'foo\bar
.Ein Nachteil
printf
ist die Leistung, da die integrierte Shellecho
viel schneller ist. Dies kommt insbesondere in Cygwin zum Tragen, wo jede Instanz eines neuen Befehls einen hohen Windows-Overhead verursacht. Als ich mein Echo-lastiges Programm von "using"/bin/echo
auf das Echo der Shell umstellte, verdoppelte sich die Leistung fast. Es ist ein Kompromiss zwischen Portabilität und Leistung. Es ist kein Slam Dunk, den man immer benutztprintf
.quelle
printf
ist heutzutage in den meisten Shells enthalten (bash, dash, ksh, zsh, yash, einige pdksh-Derivate ... also auch die für Cygwin typischen Shells). Die einzigen nennenswerten Ausnahmen sind einigepdksh
Derivate.printf
zur Ausgabe von nul Bytes verwenden möchten, aber einige Implementierungen interpretieren "\ c" in der Formatzeichenfolge, obwohl dies nicht der Fall sein sollte.printf
wird von POSIX nicht spezifiziert, wenn Sie\c
in der Formatzeichenfolge verwenden , sodassprintf
Implementierungen diesbezüglich tun können, was sie wollen. Zum Beispiel behandeln einige es genauso wie in der PWBecho
(bewirkt, dass printf beendet wird), ksh verwendet es für\cA
Steuerzeichen (für das printf-Format-Argument und für,$'...'
aber nicht fürecho
nochprint
!). Nicht sicher, was das mit dem Drucken von NUL-Bytes zu tun hat, oder beziehen Sie sich vielleicht aufksh
'sprintf '\c@'
?