Warum fügt ein Bash Here-String ein abschließendes Newline-Zeichen hinzu?

34

Die folgenden Beispiele zeigen, dass einer Here -Zeichenfolge eine neue Zeile hinzugefügt wird .
Warum wird das gemacht?

xxd -p <<<'a'  
# output: 610a

xxd -p <<<'a
'
# output: 610a0a
Peter.O
quelle

Antworten:

38

Die einfache Antwort ist, dass ksh so geschrieben ist (und bash kompatibel ist). Aber es gibt einen Grund für diese Designwahl.

Die meisten Befehle erwarten eine Texteingabe. In der Unix-Welt besteht eine Textdatei aus einer Folge von Zeilen, die jeweils in einer neuen Zeile enden . In den meisten Fällen ist daher ein abschließender Zeilenumbruch erforderlich. Ein besonders häufiger Fall ist es, die Ausgabe eines Befehls mit einer Befehlssuspension zu erfassen, auf irgendeine Weise zu verarbeiten und dann an einen anderen Befehl weiterzuleiten. Die Befehlsersetzung entfernt die letzten Zeilenumbrüche. <<<legt einen zurück.

tmp=$(foo)
tmp=${tmp//hello/world}
tmp=${tmp#prefix}
bar <<<$tmp

Bash und ksh können ohnehin keine Binärdaten manipulieren (sie können keine Nullzeichen verarbeiten), daher ist es nicht verwunderlich, dass ihre Funktionen auf Textdaten ausgerichtet sind.

Die <<<Here-String-Syntax dient meist nur der Vereinfachung, wie bei <<Here-Dokumenten. Wenn Sie keine letzte neue Zeile hinzufügen müssen, verwenden Sie echo -n(in Bash) oder printfund eine Pipeline.

Gilles 'SO - hör auf böse zu sein'
quelle
Viel gründlicher als meine Antwort.
Mike
2
Bash hat zwar Here-Strings von ksh93 ausgeliehen, aber ksh hat sie wiederum von zsh ausgeliehen, wodurch sie von der Plan 9-Shell rc bezogen wurden .
Mark Reed
2
<<<wurde in die Welt von Bourne eingeführt zsh, nicht ksh. Und es wurde durch einen ähnlichen Betreiber im Hafen Unix inspiriert von rcdenen haben nicht , dass zusätzliche Newline - Zeichen hinzufügen. Interessanterweise =(<<<text)fügt der Operator diesen Zeilenumbruch nicht hinzu zsh.
Stéphane Chazelas
Wenn Sie sich über das Interesse an dieser Antwort wundern, liegt diese Frage an SO .
Fedorqui
1
Gibt es eine Möglichkeit, die Here-Zeichenfolge zu schreiben (ohne ein anderes Hilfsprogramm wie printfusw. zu verwenden), um das Einfügen von Zeilenumbrüchen zu vermeiden bash? Like @ StéphaneChazelas darauf ist in möglich zsh.
CTodea
3

Ein Szenario, in dem es praktisch ist, Zeilenumbrüche an Here-Strings anzuhängen, ist die Verwendung des readBefehls, wenn set -emode aktiv ist. Erinnern Sie sich, set -edass ein Skript beendet wird, wenn es (mehr oder weniger) auf Anweisungen stößt, die einen Statuscode ungleich Null generieren. readBeachten Sie, dass ein Statuscode ungleich Null generiert wird, wenn eine Zeichenfolge ohne Zeilenumbrüche gefunden wird:

#!/bin/bash
set -e

# The following statement succeeds because here-strings append a newline:
IFS='' read -r <<< 'newline appended'
echo 'Made it here'

# The following statement fails because 'read' returns a non-zero status
# code when no newlines are encountered.
printf 'no newline' | IFS='' read -r
echo 'Did not make it here'
Dejay Clayton
quelle
-3

Ich denke, das ist der einzige Weg, um am Ende eines Here-Strings einen Newline-Beweis zu erhalten:

xxd <<<`echo -ne "a\n"`

Es scheint, dass der Here-String-Operator Zeilenumbrüche entfernt, sofern diese nicht in der von Ihnen übermittelten Syntax angegeben sind.

Mike
quelle
4
Es ist die Befehlsersetzung, die den letzten Zeilenumbruch bewirkt. Sie könnten dies zu vereinfachen xxd <<<$(echo a).
Gilles 'SO- hör auf böse zu sein'