Les nouvelles lignes non finales ne sont pas supprimées
Les retours à la ligne que vous recherchez sont là, mais vous ne les voyez pas, parce que vous utilisez la commande echo
sans citer la variable.
Validation :
$ 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
$
Traînée les nouvelles lignes sont supprimées
Comme @user4815162342 correctement signalée, bien que les nouvelles lignes dans la sortie ne soient pas supprimées, nouvelles lignes de queue sont supprimés par substitution de commande. Voir l'expérience ci-dessous :
$ a=$'test\n\n'
$ echo "$a"
test
$ b=$(echo "$a")
$ echo "$b"
test
$
Dans la plupart des cas, cela n'a pas d'importance, car echo
ajoutera le saut de ligne supprimé (à moins qu'il ne soit invoqué avec la directive -n
), mais il y a des cas limites où il y a plus d'un saut de ligne de fin dans la sortie d'un programme, et ils sont significatifs pour une raison quelconque.
Solutions de contournement
1. Ajouter un caractère fictif
Dans ce cas, comme @Scrutinizer mentionné, vous pouvez utiliser la solution de contournement suivante :
$ a=$(printf 'test\n\n'; printf x); a=${a%x}
$ echo "$a"
test
$
Explication : Caractère x
est ajouté à la sortie (en utilisant printf x
), après les retours à la ligne. Comme les retours à la ligne ne sont pas suivi de plus, ils ne sont pas supprimés par la substitution de commande. L'étape suivante consiste à supprimer le x
nous avons ajouté, en utilisant le %
opérateur en ${a%x}
. Maintenant nous avons la sortie originale, avec toutes les nouvelles lignes présentes ! !!
2. Lire en utilisant la substitution de processus
Au lieu d'utiliser la substitution de commande pour assigner la sortie d'un programme à une variable, nous pouvons à la place utiliser substitution de processus pour envoyer la sortie du programme au read
commande intégrée (crédit à @ormaaj ). La substitution de processus préserve toutes les nouvelles lignes. Lire la sortie dans une variable est un peu délicat, mais vous pouvez le faire comme ceci :
$ IFS= read -rd '' var < <( printf 'test\n\n' )
$ echo "$var"
test
$
Explication :
- Nous avons fixé le séparateur de champ interne pour la commande de lecture à null, avec
IFS=
. Sinon, read
n'affecterait pas la totalité de la sortie à var
mais seulement le premier jeton.
- Nous invoquons
read
avec des options -rd ''
. Le site r
permet d'empêcher la barre oblique inversée d'agir comme un caractère spécial, et avec d ''
définir le délimiteur à rien, afin que read lise la sortie entière, au lieu de seulement la première ligne.
3. Lire à partir d'un tuyau
Au lieu d'utiliser la substitution de commande ou de processus pour affecter la sortie d'un programme à une variable, nous pouvons à la place acheminer la sortie du programme vers la fonction read
(crédit à @ormaaj ). Le piping préserve également toutes les nouvelles lignes. Notez cependant que, cette fois, nous définissons le paramètre lastpipe
comportement optionnel de l'obus, en utilisant le site shopt
intégré . Ceci est nécessaire, afin que le read
est exécutée dans l'environnement actuel du shell. Sinon, la variable sera assignée dans un sous-shell, et elle ne sera pas accessible depuis le reste du script.
$ cat test.sh
#!/bin/bash
shopt -s lastpipe
printf "test\n\n" | IFS= read -rd '' var
echo "$var"
$ ./test.sh
test
$