Odpowiedzi:
Przypisanie nie usuwa znaków nowej linii, tak naprawdę to echorobi. Aby zachować te nowe linie, wystarczy umieścić cudzysłowy wokół ciągu:
echo "$testvar"
To da pożądany efekt. Zobacz poniższą transkrypcję demonstracji:
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
Powód dlaczego nowe linie są zastępowane spacjami nie jest zupełnie do czynienia z echopoleceniem, raczej jest to kombinacja rzeczy.
Gdy otrzyma wiersz poleceń, bashdzieli go na słowa zgodnie z dokumentacją dla IFSzmiennej:
IFS: wewnętrzny separator pól używany do dzielenia na słowa po interpretacji ... wartością domyślną jest
<space><tab><newline>.
Oznacza to, że domyślnie każdy z tych trzech znaków może zostać użyty do podzielenia polecenia na pojedyncze słowa. Po tym, separatory słów zniknęły, pozostała tylko lista słów.
Połącz to z echodokumentacją ( bashpolecenie wewnętrzne), a zobaczysz, dlaczego wypisywane są spacje:
echo [-neE] [arg ...]: wypisuje argumenty oddzielone spacjami, po których następuje znak nowej linii.
Kiedy używasz echo "$x", zmusza całą xzmienną, aby była pojedynczym słowem zgodnie z bash, dlatego nie jest podzielona. Możesz to zobaczyć za pomocą:
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
Tutaj countfunkcja po prostu wypisuje liczbę podanych argumentów. 1 2 3I a b c dwarianty pokazać go w akcji.
Następnie wypróbowujemy to z dwiema odmianami xzmiennej. Jedna bez cytatów wynika, że istnieją cztery słowa "test", "1", "test"i "2". Dodanie cudzysłowów sprawia, że jest to jedno słowo "test 1\ntest 2".
Wynika to ze zmiennej IFS (Internal Field Separator) , która zawiera znak nowej linii.
$ cat xx1
1
2
$ A=`cat xx1`
$ echo $A
1 2
$ echo "|$IFS|"
|
|
Aby obejść ten problem, należy tymczasowo zresetować IFS, aby nie zawierał nowej linii :
$ IFSBAK=$IFS
$ IFS=" "
$ A=`cat xx1` # Can use $() as well
$ echo $A
1
2
$ IFS=$IFSBAK
Aby ODWRÓCIĆ tę straszną zmianę dla IFS:
IFS=$IFSBAK
echo "$(IFS=''; cat text.txt)"
Bash -ge 4 ma wbudowane mapfile do wczytywania wierszy ze standardowego wejścia do zmiennej tablicowej.
help mapfile
mapfile < file.txt lines
printf "%s" "${lines[@]}"
mapfile -t < file.txt lines # strip trailing newlines
printf "%s\n" "${lines[@]}"
Zobacz też:
http://bash-hackers.org/wiki/doku.php/commands/builtin/mapfile
Twoja zmienna jest ustawiona poprawnie przez testvar=$(cat test.txt). Aby wyświetlić tę zmienną, która zawiera znaki nowego wiersza, wystarczy dodać podwójne cudzysłowy, np
echo "$testvar"
Oto pełny przykład:
$ printf "test1\ntest2" > test.txt
$ testvar=$(<test.txt)
$ grep testvar <(set)
testvar=$'test1\ntest2'
$ echo "$testvar"
text1
text2
$ printf "%b" "$testvar"
text1
text2
envdirNarzędzie pozwala w łatwy sposób to zrobić. envdirużywa plików do reprezentowania zmiennych środowiskowych, z mapowaniem nazw plików na nazwy env var i mapowaniem zawartości pliku na wartości env var. Jeśli zawartość pliku zawiera znaki nowej linii, tak samo będzie z env var.