So fügen Sie bei Verwendung von Echo neue Zeilen hinzu

42

Warum fügt der folgende Befehl keine neuen Zeilen in die generierte Datei ein und was ist die Lösung?

$ echo "Line 1\r\nLine2" >> readme.txt

$ cat readme.txt 
Line 1\r\nLine2
Saeid Yazdani
quelle
6
Ist echoobligatorisch? Sie können verwenden printf.
Archemar
Ich wusste nichts über printf, mit printf funktioniert es: P ... also, was bringt es, wenn nicht mit Echo gearbeitet wird?
Saeid Yazdani
Gehört \rInclude zur Ausgabe oder ist es Teil von CRLFNewline?
Donnerstag,
9
Es gibt viele verschiedene Implementierungen von echoBefehlen, die nicht miteinander kompatibel sind. Daher wird empfohlen, mehr Standardwerkzeug als zu verwenden printf. Unter unix.stackexchange.com/questions/65803/… finden Sie eine erweiterte Übersicht über das Problem.
Jimmy
In Stack Overflow gibt Echo Newline in Bash Literal aus \ nEcho Newline in Bash gibt Literal aus \ n hat einige nützliche Antworten.
Graham Perrin

Antworten:

38

echo


Eine echoImplementierung, die sich strikt an die Single Unix-Spezifikation hält, fügt neue Zeilen hinzu, wenn Sie Folgendes tun:

echo 'line1\nline2'

Das ist aber kein verlässliches Verhalten. Tatsächlich gibt es wirklich kein Standardverhalten, das Sie erwarten können echo.

OPERANDEN

string

Ein String, der in die Standardausgabe geschrieben werden soll. Ist der erste Operand -noder enthält einer der Operanden ein < \Backslash> -Zeichen, sind die Ergebnisse implementierungsdefiniert .

Auf XSI-konformen Systemen wird der erste Operand -nals Zeichenfolge und nicht als Option behandelt . Die folgenden Zeichenfolgen müssen auf XSI-konformen Systemen innerhalb eines der Argumente erkannt werden:

\a- Schreiben Sie einen <alert> .

\b- Schreiben Sie ein <Backspace> .

\c- Unterdrücken Sie die <newline> , die ansonsten auf das letzte Argument in der Ausgabe folgt. Alle Zeichen, die den \cin den Argumenten folgen , werden ignoriert.

\f- Schreiben Sie einen <Formular-Feed> .

\n- Schreiben Sie eine <newline> .

\r- Schreiben Sie einen <Wagenrücklauf> .

\t- Schreiben Sie ein <tab> .

\v- Schreiben Sie einen <Vertical-Tab> .

\\- Schreiben Sie ein <Backslash> -Zeichen.

\0num- Schreiben Sie einen 8-Bit-Wert, der die null-, ein-, zwei- oder dreistellige Oktalzahl ist num.

Und so gibt es wirklich keinen allgemeinen Weg, wie man eine neue Zeile schreibt echo, außer dass man sich im Allgemeinen darauf verlassen kann echo, dies einfach zu tun.

Eine bashShell entspricht normalerweise nicht der Spezifikation und behandelt die -nund andere Optionen, aber auch das ist ungewiss. Du kannst tun:

shopt -s xpg_echo
echo hey\\nthere

hey
there

Und nicht einmal das ist notwendig, wenn bashmit der Build-Time-Option gebaut wurde ...

--enable-xpg-echo-default

echoVeranlassen Sie das eingebaute Expandieren von Zeichen mit umgekehrten Schrägstrichen standardmäßig, ohne dass die -eOption erforderlich ist . Dies setzt den Standardwert der xpg_echoShell-Option auf on, wodurch sich die Bash echomehr wie die in der Single Unix Specification, Version 3, angegebene Version verhält . Eine Beschreibung der echoerkannten Escape-Sequenzen finden Sie unter Bash Builtins .


printf


Auf der anderen Seite ist printfdas Verhalten im Vergleich ziemlich zahm.

RATIONALE

Das printfDienstprogramm wurde hinzugefügt, um Funktionen bereitzustellen, die in der Vergangenheit von bereitgestellt wurden echo. Aufgrund der unüberbrückbaren Unterschiede in den verschiedenen vorhandenen Versionen echoweist die Version jedoch nur wenige Besonderheiten auf, so dass diese diesem neuen printfDienstprogramm überlassen bleiben, das auf einem Dienstprogramm im neunten Editionssystem basiert.

Der Abschnitt EXTENDED DESCRIPTION (ERWEITERTE BESCHREIBUNG) entspricht fast genau der printf()Funktion im ISO-C-Standard, obwohl er in der Dateiformatnotation in der XBD-Dateiformatnotation beschrieben wird .

Es behandelt Format-Strings, die ihre Argumente beschreiben - das kann eine beliebige Anzahl von Dingen sein, aber für Strings sind es so ziemlich entweder %bYte-Strings oder Literal- %sTrings. Anders als die %fOrmats im ersten Argument verhält es sich am %bähnlichsten wie ein Yte-String-Argument, außer dass es das \cEscape nicht behandelt .

printf ^%b%s$ '\n' '\n' '\t' '\t'

^
\n$^    \t$

Sehen Sie, warum ist printfbesser als echo? für mehr.


echo() printf


Sie könnten Ihre eigenen Standards konform schreiben echowie ...

echo(){
    printf '%b ' "$@\n\c"
}

... was eigentlich immer automatisch das Richtige tun sollte.

Eigentlich nein ... Das gibt ein Literal \nam Ende der Argumente aus, wenn das letzte Argument mit einer ungeraden Anzahl von <Backslashes> endet .

Das tut es aber nicht:

echo()
    case    ${IFS- } in
    (\ *)   printf  %b\\n "$*";;
    (*)     IFS=\ $IFS
            printf  %b\\n "$*"
            IFS=${IFS#?}
    esac
mikeserv
quelle
+1 für die standardmäßig zu verwendende shopt -s xpg_echoOption . echo-e
Vignesh Raja
Diese Lösung funktioniert nicht ohne -e. Ich bin überrascht, dass niemand das bemerkt hat, außer vielleicht @HaydeSchiff
ha9u63ar
@ ha9u63ar - äh ... hast du das gelesen?
mikeserv
27

Übergeben Sie das Flag -e an echo, damit maskierte Zeichen wie "\ r \ n" wie folgt analysiert werden:

echo -e "Line 1\r\nLine2" >> readme.txt
Hayden Schiff
quelle
Eine nette einfache "-e" Option, um Escape-Sequenzen zum Laufen zu bringen - es steht auf einer anderen Antwort, echodie unzuverlässig ist und im Gegensatz zu anderen Standards nicht den Standards folgt printf.
Edward
1
Stellen Sie sicher, dass Ihr Skript kein Literal enthält, z. B. in einem tr -d "\n"Befehl.
Noumenon
8

In allen Versionen von bash, die ich verwendet habe, können Sie entweder interaktiv oder in einem Skript eine wörtliche Newline in eine Zeichenfolge einfügen, sofern die Zeichenfolge in Anführungszeichen steht.

Interaktiv:

$ echo "Line one
> Line two"
Line one
Line two
$

In einem Skript:

echo "Line one
Line two"
Digitales Trauma
quelle
4
echo -e "Line 1\r\nLine2" >> readme.txt

Weitere Nutzungsmöglichkeiten:

man echo
zodo
quelle
2

Die Leute haben bereits angemessen geantwortet, aber ich lehne es ab, eine Welt zu akzeptieren, in der Echo jede andere Option als akzeptiert -n.

nl='
'
echo Line 1"$nl"Line 2"$nl"Line 3
Staven
quelle
1

Wenn Sie einen Charakter haben, der nicht Teil der Nachricht ist, können Sie sed weiterleiten

$ echo "Time on the next line:@$(date +"%Y-%m-%dT%T%z")" | sed -e's/@/\n/g'
Time on the next line:
2016-03-25T10:12:39-0500
verisimilidude
quelle