Wie im folgenden Beispiel und wie in meiner letzten Frage In Bash, wo ist das nachgestellte Newline-Zeichen geblieben? Ich möchte wissen, "warum" es passiert
x="$(echo -ne "a\nb\n")" ; echo -n "$x" | xxd -p
# Output is: 610a62
# The trailing newline from the 'echo' command
# has been "deleted" by Command Substitution
Ich gehe davon aus, dass es einen sehr wichtigen Grund für eine Shell-Aktion geben muss, nämlich die Befehlsersetzung, um tatsächlich einige Daten aus der Befehlsausgabe zu löschen, die sie ersetzt ...
aber ich kann mich nicht darum kümmern , wie es scheint das genaue Gegenteil von dem, was es soll .. also tun. Die Ausgabe eines Befehls zurück in den Skriptprozess zu leiten ... Ein Zeichen zurückzuhalten, erscheint mir seltsam, aber ich nehme an, es gibt einen vernünftigen Grund dafür ... Ich bin gespannt darauf, herauszufinden, was dieser Grund ist. .
Antworten:
Weil die Shell ursprünglich nicht als vollständige Programmiersprache gedacht war.
Es ist ziemlich schwierig, ein Trailing
\n
aus einer Befehlsausgabe zu entfernen . Zu Anzeigezwecken beenden jedoch fast alle Befehle ihre Ausgabe mit\n
, daher muss es eine einfache Möglichkeit geben, sie zu entfernen, wenn Sie sie in einem anderen Befehl verwenden möchten. Die automatische Entfernung mit der$()
Konstruktion war die gewählte Lösung.Vielleicht akzeptieren Sie diese Frage als Antwort:
Können Sie einen einfachen Weg finden, um das Trailing zu entfernen,
\n
wenn dies im folgenden Befehl nicht automatisch gemacht wurde?Beachten Sie, dass Anführungszeichen erforderlich sind, um das Zerschlagen von doppelten Leerzeichen zu verhindern, die in formatierten Daten auftreten können.
quelle
shopt
Möglichkeit gibt , Ihr beschriebenes Standardverhalten zu ändern, würde ich mich wieder freuen ... Ich finde es schwierig zu glauben, dass Bash / Linux / Unix eine so wichtige Funktion wie "stdout erfassen" verschmutzen würde, nur weildate
dies nicht der Fall ist a with / without '\ n' Option ... Die offensichtliche Lösung wäre, dass Bash (oder eine andere Shell) eineshopt
für diese hat ... Kennen Sie eine? .. und haben Sie Verweise, die über das Warum und Warum dieser Ausgabe sprechen? ... und warum gibt es keinedate
\ n Option .. Es sollte!$()
alternativen Syntax.{ echo -n "The current date is "; var="$(date; echo -e x)"; var="${var%x}"; echo -n "$var"; echo ", have a good day!"; }
.. also sei es :)date
würde nur funktionieren, aber ich habe nurdate
als Beispiel für einen Befehl verwendet ..Es ist Teil des Standards :
Natürlich ist der Standard wahrscheinlich so geschrieben, weil
ksh
es so oder so war, aber es ist der Standard und dokumentiertes Verhalten. Wenn Sie es nicht mögen, verwenden Sie Perl oder etwas anderes, mit dem Sie die nachgestellten Zeilenumbrüche beibehalten können.quelle
Nun, es macht Sinn für mich. Die neue Zeile ist in der normalen Befehlsausgabe nur an erster Stelle vorhanden, sodass die Eingabeaufforderung angezeigt wird, nachdem der Befehl in einer neuen Zeile ausgeführt wurde. Die neue Zeile ist in den meisten Fällen nicht Teil der ursprünglichen Ausgabe, sondern dient zum Aufräumen des Bildschirms. Wenn Sie die Ausgabe eines Befehls analysieren, ist der Zeilenumbruch am Ende normalerweise problematisch. Warum gibt der
wc
Befehl 2 Textzeilen aus? Oh, tut es nicht, es gibt eine Zeile gefolgt von einer neuen Zeile aus. Wenn Sie analysierenwc
, möchten Sie sich keine Sorgen darüber machen, dass es zwei Ausgabezeilen gibt - es gibt eigentlich keine, es gibt nur eine.quelle
\n
im ursprünglichenstdout
Stream durch Befehlssubstitution entfernt wird. dh Bei meinen ursprünglichen Daten (sehr wichtigen Daten) wurden nachgestellte Zeilenumbrüche entfernt, auch wenn die Daten in "Anführungszeichen" gesetzt sind. Ich einigermaßen verstehen , wie und warum Wort Splitting funktioniert, aber ich habe absolut keine Ahnung , warum Befehl Substitution nur Streifen Zeilenumbrüche und nur Hinter denjenigen.Ich bin auf dasselbe Problem gestoßen und habe das folgende Beispiel gefunden. Anscheinend hat das Zitieren der Situation geholfen, zumindest für mich:
http://tldp.org/LDP/abs/html/commandsub.html .
quelle
$str
, die die Zeichenfolge enthält"a b c"
. Wenn Sie passieren$str
zuecho
ohne Anführungszeichen (echo $str
),echo
erhaltena
,b
undc
als drei getrennte Argumente. Das Leerzeichen zwischen den Argumenten ist Ihrer Shell egal.echo
Diese Argumente werden dann mit Leerzeichen zwischen den einzelnen Argumenten gedruckt, sodass Sie Folgendes erhalten"a b c"
. Wenn Sie die Variableecho
mit Anführungszeichen (echo "$str"
) übergeben, sieht die Shell sie als ein Argument undecho
empfängt sie als solches, sodass das Leerzeichen nicht reduziert wird. Gleiches gilt für Zeilenumbrüche.-n
Flag nicht übergeben wird, wird derecho
Ausgabe eine abschließende neue Zeile hinzugefügt, sodass beide Echos in Ihrem Beispiel abschließende neue Zeilen haben. Wenn Sie jedochecho -n $dir_listing
oder versuchenecho -n "$dir_listing"
, werden Sie feststellen, dass keine nachgestellten Zeilen mit oder ohne Anführungszeichen gedruckt werden$dir_listing
, was darauf hindeutet, dass das Problem bei der Befehlsersetzung liegt.warum
echo "hello "
verschlingt (ohne die Anführungszeichen) den Raum? Der Wert von IFS-Zeichen wird von der Shell als Begrenzer angesehen, daher werden die nachfolgenden Zeichen (die nichts begrenzen) entfernt. Die commend-Ersetzung führt lediglich die commends in einer Sub-Shell aus, daher folgt sie derselben Logik.quelle
x="hello "
undx="hello "
verlieren alle ihre Leerzeichen, wenn sie überecho $x
... angezeigt werden . Es geht jedoch nur die allerletzte Zeile der Befehlsersetzung verloren.IFS
hat nichts mit dem Entfernen von Zeilenumbrüchen am Ende von Befehlsersetzungen zu tun.