Nicht nachfolgende Zeilenumbrüche werden nicht entfernt
Die gesuchten Zeilenumbrüche sind da, Sie sehen sie einfach nicht, weil Sie sie verwenden, echo
ohne die Variable in Anführungszeichen zu setzen .
Validierung :
$ a=$( df -H )
$ echo $a
Filesystem Size Used Avail Use% Mounted on /dev/sda3 276G 50G 213G 19% / udev 2.1G 4.1k 2.1G 1% /dev tmpfs 832M 820k 832M 1% /run none 5.3M 0 5.3M 0% /run/lock none 2.1G 320k 2.1G 1% /run/shm
$ echo "$a"
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 276G 50G 213G 19% /
udev 2.1G 4.1k 2.1G 1% /dev
tmpfs 832M 820k 832M 1% /run
none 5.3M 0 5.3M 0% /run/lock
none 2.1G 320k 2.1G 1% /run/shm
$
Nachgestellte Zeilenumbrüche werden entfernt
Wie @ user4815162342 richtig hervorhob , werden nachfolgende Zeilenumbrüche durch Befehlsersetzung entfernt, obwohl Zeilenumbrüche in der Ausgabe nicht entfernt werden. Siehe Experiment unten:
$ a=$'test\n\n'
$ echo "$a"
test
$ b=$(echo "$a")
$ echo "$b"
test
$
In den meisten Fällen spielt dies keine Rolle, da echo
die entfernte neue Zeile hinzugefügt wird (es sei denn, sie wird mit der -n
Option aufgerufen ). In einigen Randfällen gibt es jedoch mehr als eine nachfolgende Zeile in der Ausgabe eines Programms, und sie sind für diese von Bedeutung irgendein Grund.
Problemumgehungen
1. Fügen Sie ein Dummy-Zeichen hinzu
In diesem Fall können Sie, wie bei @Scrutinizer erwähnt, die folgende Problemumgehung verwenden:
$ a=$(printf 'test\n\n'; printf x); a=${a%x}
$ echo "$a"
test
$
Erläuterung: Nach den Zeilenumbrüchen wirdx
der Ausgabe (usingprintf x
) einZeichenhinzugefügt. Da die Zeilenumbrüche nicht mehr nachlaufen , werden sie durch die Befehlsersetzung nicht entfernt. Der nächste Schritt besteht darin, dasx
hinzugefügte Element mithilfe des%
Operators inzu entfernen${a%x}
. Jetzt haben wir die Originalausgabe mit allen Zeilenumbrüchen !!!
2. Lesen Sie mit Prozessersetzung
Anstatt die Befehlssubstitution zu verwenden, um die Ausgabe eines Programms einer Variablen zuzuweisen, können wir stattdessen die Prozessersetzung verwenden , um die Ausgabe des Programms dem read
integrierten Befehl zuzuführen (Gutschrift an @ormaaj ). Durch die Prozessersetzung bleiben alle Zeilenumbrüche erhalten. Das Lesen der Ausgabe in eine Variable ist etwas schwierig, aber Sie können dies folgendermaßen tun:
$ IFS= read -rd '' var < <( printf 'test\n\n' )
$ echo "$var"
test
$
Erläuterung:
- Wir setzen das interne Feldtrennzeichen für den Lesebefehl auf null mit
IFS=
. Andernfalls read
würde nicht die gesamte Ausgabe zugewiesen var
, sondern nur das erste Token.
- Wir rufen
read
mit Optionen auf -rd ''
. Das r
ist zum Verhindern des umgekehrten Schrägstrich als Sonderzeichen zu handeln und mit d ''
den Begrenzer zu nichts festgelegt, so dass Lesen Sie die gesamte Ausgabe liest, statt nur die erste Zeile.
3. Lesen Sie aus einem Rohr
Anstatt eine Befehls- oder Prozessersetzung zu verwenden, um die Ausgabe eines Programms einer Variablen zuzuweisen, können wir stattdessen die Ausgabe des Programms an den read
Befehl weiterleiten (Gutschrift an @ormaaj ). Durch die Rohrleitungen bleiben auch alle Zeilenumbrüche erhalten. Beachten Sie jedoch, dass wir diesmal das lastpipe
optionale Verhalten der Shell mithilfe der integrierten Funktion shopt
festlegen . Dies ist erforderlich, damit der read
Befehl in der aktuellen Shell-Umgebung ausgeführt wird. Andernfalls wird die Variable in einer Subshell zugewiesen und kann vom Rest des Skripts nicht aufgerufen werden.
$ cat test.sh
shopt -s lastpipe
printf "test\n\n" | IFS= read -rd '' var
echo "$var"
$ ./test.sh
test
$