Der echo
Befehl enthält nicht den vollständigen Text, den ich ihm gebe. Zum Beispiel, wenn ich tue:
$ echo ' echo PARAM=` grep $ARG /var/tmp/setfile | awk '{print $2}' ` '
Es gibt aus:
echo PARAM=` grep $ARG /var/tmp/setfile | awk {print } `
Die einfachen Anführungszeichen ( '
), die ich in meinem Echo-Befehl hatte, sind nicht enthalten. Wenn ich zu doppelten Anführungszeichen wechsle:
$ echo " echo PARAM=` grep $ARG /var/tmp/setfile | awk '{print $2}' ` "
echo
gibt gar nichts aus! Warum werden im ersten Beispiel die einfachen Anführungszeichen weggelassen und im zweiten Beispiel nichts ausgegeben? Wie kann ich genau das ausgeben, was ich eingegeben habe?
Antworten:
Ihre Shell interpretiert die Anführungszeichen, sowohl
'
als auch"
, bevor sie überhaupt ankommenecho
. Im Allgemeinen setze ich meine Argumente in doppelte Anführungszeichen, um sie wiederzugeben, auch wenn sie nicht erforderlich sind. beispielsweise:Wenn Sie also in Ihrem ersten Beispiel wörtliche Anführungszeichen in Ihre Ausgabe aufnehmen möchten, müssen diese entweder maskiert werden:
Oder sie müssen bereits in einem in Anführungszeichen gesetzten Argument verwendet werden (aber es kann nicht dieselbe Art von Anführungszeichen sein, oder Sie müssen es trotzdem umgehen):
In Ihrem zweiten Beispiel führen Sie eine Befehlsersetzung in der Mitte der Zeichenfolge aus:
Dinge, die mit anfangen,
$
werden auch speziell von der Shell behandelt - sie werden als Variablen behandelt und durch ihre Werte ersetzt. Da höchstwahrscheinlich keine dieser Variablen in Ihrer Shell festgelegt ist, wird sie tatsächlich nur ausgeführtDa
grep
nur ein Argument angezeigt wird, wird davon ausgegangen, dass es sich bei dem Argument um das Muster handelt, nach dem Sie suchen, und dass die Position, von der die Daten gelesen werden sollen, stdin ist, sodass das Warten auf Eingaben blockiert wird. Deshalb scheint Ihr zweiter Befehl einfach zu hängen.Dies passiert nicht, wenn Sie das Argument in Anführungszeichen setzen (weshalb Ihr erstes Beispiel fast funktioniert hat). Dies ist also eine Möglichkeit, die gewünschte Ausgabe zu erhalten:
Sie können es auch in doppelte Anführungszeichen setzen, aber dann müssen Sie das
$
s schließen, damit die Shell sie nicht als Variablen auflöst, und die Backticks, damit die Shell die Befehlssubstitution nicht sofort ausführt:quelle
Ich werde nicht näher darauf eingehen, warum sich Ihre Versuche so verhalten, wie sie es tun, denn Michael Mrozeks Antwort deckt dies gut ab. Kurz gesagt, alles zwischen einfachen Anführungszeichen (
'…'
) wird wörtlich interpretiert (und insbesondere das erste'
markiert das Ende der wörtlichen Zeichenfolge), während`
und$
behalten ihre besondere Bedeutung zwischen"…"
.Es gibt keine Anführungszeichen in einfachen Anführungszeichen, daher können Sie keine einfachen Anführungszeichen in einfache Anführungszeichen setzen. Es gibt jedoch eine Redewendung, die so aussieht:
Dies wird ausgegeben
foo'bar
, weil das Argument toecho
aus der in Anführungszeichen gesetzten dreistelligen Zeichenfolge bestehtfoo
, die mit dem einzelnen Zeichen verkettet ist'
(das durch Schützen des Zeichens'
vor seiner speziellen Bedeutung durch das Vorhergehende erhalten wird\
) und mit der in Anführungszeichen gesetzten dreistelligen Zeichenfolge verkettet istbar
. Obwohl dies im Hintergrund nicht der'\''
Fall ist , können Sie sich vorstellen , ein einfaches Anführungszeichen in eine Zeichenfolge mit einfachen Anführungszeichen einzufügen.Wenn Sie komplexe mehrzeilige Zeichenfolgen drucken möchten, ist das Dokument hier ein besseres Werkzeug . Ein Here-Dokument besteht aus zwei Zeichen,
<<
gefolgt von einer Markierung, z. B.<<EOF
Textzeilen, und der Endmarkierung allein in der Zeile. Wenn der Marker in irgendeiner Weise in Anführungszeichen gesetzt wird ('EOF'
oder"EOF"
oder\EOF
'E "" OF' oder ...), wird der Text wörtlich interpretiert (wie in einfachen Anführungszeichen, außer dass es sich sogar'
um ein gewöhnliches Zeichen handelt). Wenn der Marker überhaupt nicht in Anführungszeichen gesetzt ist, wird der Text wie eine doppelte Anführungszeichenfolge interpretiert,$\`
wobei sein besonderer Status beibehalten wird (aber"
und Zeilenumbrüche werden wörtlich interpretiert).quelle
Okay, das wird funktionieren: -
Testen Sie es hier: -
quelle
Gilles 'Vorschlag , ein Dokument hier zu verwenden, ist wirklich nett und funktioniert sogar in Skriptsprachen wie Perl. Als konkretes Beispiel, basierend auf seiner Antwort auf die Frage des OP,
Zugegeben, dieses Beispiel ist ein wenig erfunden, aber ich habe festgestellt, dass es eine nützliche Technik ist, um beispielsweise SQL-Anweisungen an
psql
(anstelle voncat
) zu senden .(Beachten Sie, dass anstelle des
#
obigen generischen Anführungszeichens ein beliebiges nicht-alphanumerisches Nicht-Leerzeichen verwendet werden kann. Der Hash schien jedoch für dieses Beispiel von Bedeutung zu sein und wird nicht als Kommentar behandelt.)quelle
Nehmen wir Ihr Kommando an
und teilen Sie es zuerst in Wörter auf, wobei Sie das Leerzeichen ohne Anführungszeichen als Trennzeichen verwenden:
Als nächstes führen wir eine Parametererweiterung durch: expand,
$…
aber nicht inside'…'
. Da$2
leer ist (es sei denn, Sie setzen es über zBset -- …
), wird es durch einen leeren String ersetzt.Führen Sie als Nächstes das Entfernen von Zitaten durch.
Diese Argumente werden dann an echo übergeben, das sie durch ein einzelnes Leerzeichen getrennt nacheinander ausgibt.
Ich hoffe, dass diese schrittweise Anleitung das beobachtete Verhalten klarer macht. Um das Problem zu vermeiden, schließen Sie einfache Anführungszeichen wie folgt:
Dies beendet die Zeichenfolge in einfachen Anführungszeichen, fügt dem Wort ein einfaches Anführungszeichen (ohne Anführungszeichen) hinzu und beginnt dann eine neue Zeichenfolge in einfachen Anführungszeichen, ohne das Wort zu trennen.
quelle