Odpowiedzi:
Przypisanie nie usuwa znaków nowej linii, tak naprawdę to echo
robi. 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 echo
poleceniem, raczej jest to kombinacja rzeczy.
Gdy otrzyma wiersz poleceń, bash
dzieli go na słowa zgodnie z dokumentacją dla IFS
zmiennej:
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 echo
dokumentacją ( bash
polecenie 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łą x
zmienną, 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 count
funkcja po prostu wypisuje liczbę podanych argumentów. 1 2 3
I a b c d
warianty pokazać go w akcji.
Następnie wypróbowujemy to z dwiema odmianami x
zmiennej. 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
envdir
Narzędzie pozwala w łatwy sposób to zrobić. envdir
uż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.