L'affectation ne supprime pas les caractères de nouvelle ligne, c'est en echofait cela. Vous devez simplement mettre des guillemets autour de la chaîne pour conserver ces nouvelles lignes:
echo "$testvar"
Cela donnera le résultat souhaité. Consultez la transcription suivante pour une démonstration:
pax> cat num1.txt ; x=$(cat num1.txt)
line 1
line 2
pax> echo $x ; echo '===' ; echo "$x"
line 1 line 2
===
line 1
line 2
La raison pour laquelle les retours à la ligne sont remplacés par des espaces n'est pas entièrement liée à la echocommande, mais plutôt à une combinaison de choses.
Lorsqu'on lui donne une ligne de commande, la bashdivise en mots selon la documentation de la IFSvariable:
IFS: Le séparateur de champ interne qui est utilisé pour la division de mot après l'expansion ... la valeur par défaut est <space><tab><newline>.
Cela spécifie que, par défaut, l'un de ces trois caractères peut être utilisé pour diviser votre commande en mots individuels. Après cela, les séparateurs de mots ont disparu, il ne vous reste plus qu'une liste de mots.
Combinez cela avec la echodocumentation (une bashcommande interne), et vous verrez pourquoi les espaces sont affichés:
echo [-neE] [arg ...]: Affiche les arguments , séparés par des espaces, suivis d'une nouvelle ligne.
Lorsque vous utilisez echo "$x", cela force la xvariable entière à être un seul mot selon bash, par conséquent, il n'est pas divisé. Vous pouvez le voir avec:
pax> function count {
...> echo $#
...> }
pax> count 1 2 3
3
pax> count a b c d
4
pax> count $x
4
pax> count "$x"
1
Ici, la countfonction affiche simplement le nombre d'arguments donnés. Les variantes 1 2 3et le a b c dmontrent en action.
Ensuite, nous l'essayons avec les deux variantes de la xvariable. Celui sans guillemets montre qu'il ya quatre mots, "test", "1", "test"et "2". L'ajout des guillemets en fait un seul mot "test 1\ntest 2".