L'assegnazione non rimuove i caratteri di nuova riga, in realtà è il echofarlo. Devi semplicemente inserire virgolette attorno alla stringa per mantenere quelle nuove righe:
echo "$testvar"
Questo darà il risultato desiderato. Vedere la seguente trascrizione per una demo:
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
Il motivo per cui le nuove righe vengono sostituite con spazi non è interamente a che fare con il echocomando, piuttosto è una combinazione di cose.
Quando viene fornita una riga di comando, la bashdivide in parole secondo la documentazione per la IFSvariabile:
IFS: il separatore di campo interno utilizzato per la suddivisione delle parole dopo l'espansione ... il valore predefinito è <space><tab><newline>.
Ciò specifica che, per impostazione predefinita, uno qualsiasi di questi tre caratteri può essere utilizzato per dividere il comando in singole parole. Dopodiché, i separatori di parole sono spariti, tutto ciò che ti resta è un elenco di parole.
Combinalo con la echodocumentazione (un bashcomando interno) e vedrai perché gli spazi vengono emessi:
echo [-neE] [arg ...]: restituisce gli argomenti, separati da spazi, seguiti da una nuova riga.
Quando lo usi echo "$x", forza l'intera xvariabile ad essere una singola parola in base a bash, quindi non è divisa. Puoi vederlo con:
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
Qui, la countfunzione stampa semplicemente il numero di argomenti forniti. Le varianti 1 2 3e a b c dlo mostrano in azione.
Quindi lo proviamo con le due varianti sulla xvariabile. L'uno senza citazioni spettacoli che ci sono quattro parole "test", "1", "test"e "2". Aggiungendo le virgolette diventa una sola parola "test 1\ntest 2".