Nicht nachfolgende Zeilenumbrüche werden nicht entfernt
Die gesuchten Zeilenumbrüche sind da, Sie sehen sie einfach nicht, weil Sie sie verwenden, echoohne 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 echodie entfernte neue Zeile hinzugefügt wird (es sei denn, sie wird mit der -nOption 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 wirdxder 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, dasxhinzugefü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 readintegrierten 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 readwürde nicht die gesamte Ausgabe zugewiesen var, sondern nur das erste Token.
- Wir rufen
readmit Optionen auf -rd ''. Das rist 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 readBefehl weiterleiten (Gutschrift an @ormaaj ). Durch die Rohrleitungen bleiben auch alle Zeilenumbrüche erhalten. Beachten Sie jedoch, dass wir diesmal das lastpipeoptionale Verhalten der Shell mithilfe der integrierten Funktion shoptfestlegen . Dies ist erforderlich, damit der readBefehl 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
$