Warum entfernt die Bash \ n in $ (Cat-Datei)?

24

Wenn ich die Akte habe, die input.txtenthält:

hello
world
!

Wenn Sie dann den Befehl bash ausführen, wird Folgendes echo $(cat input.txt)ausgegeben:

hello world !

Warum und wie kann ich das Problem beheben, um genau das auszugeben, was in der Datei enthalten ist, wie es in der Datei enthalten ist?

f.ardelian
quelle

Antworten:

32

Wenn du benutzt

echo "$(cat input.txt)"

es wird richtig funktionieren.

Wahrscheinlich wird die Eingabe von Echo durch Zeilenumbrüche getrennt und als separate Befehle behandelt, sodass das Ergebnis ohne Zeilenumbrüche angezeigt wird.

arian
quelle
Nett! Was ist der Unterschied (falls vorhanden) zwischen $ () und Backticks? (Sorry, wenn dies zu tangential ist)
Chan-Ho Suh
Sie sind gleichwertig, mit Ausnahme der Tatsache, dass $ (...) einfacher zu verschachteln ist. In beiden Fällen wird das Ergebnis, wenn Sie es nicht in Anführungszeichen setzen, in mehrere Argumente im Leerraum unterteilt.
James Henstridge
3
Das letzte Zeilenumbruchzeichen wird jedoch auch in doppelten Anführungszeichen weggelassen. Im Gegensatz dazu wird der Backtick-Operator von Perl auf die gesamte Ausgabe des Befehls einschließlich aller Zeilenumbrüche ausgeweitet.
Keith Thompson
6
@KeithThompson Ja, die Befehlsersetzung entfernt alle nachgestellten Zeilenumbrüche aus der Ausgabe. echo "$(date) something"Dies hat den Vorteil, dass z. B. die nachgestellte Zeile von der Ausgabe des Datums entfernt wird und das Echo das Datum und "etwas" in derselben Zeile ausgibt. Wenn Sie eine Datei oder eine Befehlsausgabe unverändert speichern müssen, verwenden Sie mapfile ( help mapfile) read -rd ''oder eine while- Leseschleife .
Geirha
Vielen Dank an alle :-) Ich habe aus jedem Kommentar hier etwas gelernt!
Chan-Ho Suh
2

Zitat aus der Bash-Handbuchseite, Abschnitt Command Substitution:

Eingebettete Zeilenumbrüche werden nicht gelöscht, können jedoch während der Wortteilung entfernt werden.

Ein wenig weiter, gleicher Abschnitt:

Wenn die Ersetzung in doppelten Anführungszeichen steht, werden Wortteilung und Pfadnamenerweiterung für die Ergebnisse nicht ausgeführt.

Deshalb echo "$(cat /etc/passwd)" funktioniert.

Beachten Sie außerdem , dass durch das Ersetzen von Befehlen durch POSIX-Spezifikationen nachfolgende Zeilenumbrüche entfernt werden:

$ echo "$(printf "one\ntwo\n\n\n")"
one
two

Das Ausgeben einer Datei über $(cat file.txt)kann daher zum Verlust nachgestellter Zeilenumbrüche führen, und dies kann ein Problem sein, wenn die Integrität der gesamten Datei Vorrang hat.

Sergiy Kolodyazhnyy
quelle
2

Sie können Zeilenumbrüche beibehalten, indem Sie beispielsweise IFS auf leer setzen:

$ IFS=
$ a=$(cat links.txt)
$ echo "$a"
link1
link2
link3
Sarnath Jegadeesan
quelle