it-swarm.com.de

Dateiinhalt in Unix-Variable mit Zeilenumbrüchen

Ich habe eine Textdatei test.txt mit folgendem Inhalt:

text1
text2 

Und ich möchte den Inhalt der Datei einer UNIX-Variablen zuweisen, aber wenn ich das mache: 

testvar=$(cat test.txt)
echo $testvar

das Ergebnis ist: 

text1 text2

anstatt

text1
text2 

Kann mir jemand eine Lösung dafür vorschlagen?

83
Hugo

Die Zuweisung entfernt die Zeilenumbrüche nicht , sondern das echo. Sie müssen einfach Anführungszeichen um den String setzen, um diese Zeilenumbrüche beizubehalten:

echo "$testvar"

So erhalten Sie das gewünschte Ergebnis. Das folgende Protokoll enthält eine 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

Der Grund , warum Zeilenumbrüche durch Leerzeichen ersetzt werden, hat nicht ganz mit dem Befehl echo zu tun, sondern ist eine Kombination von Sachen.

Wenn eine Befehlszeile angegeben wird, teilt bash sie gemäß der Dokumentation für die Variable IFS in Wörter auf:

IFS: Das interne Feldtrennzeichen, das nach der Erweiterung für die Wortteilung verwendet wird. Der Standardwert ist <space><tab><newline>.

Dies gibt an, dass standardmäßig eines dieser drei Zeichen verwendet werden kann, um Ihren Befehl in einzelne Wörter aufzuteilen. Danach sind die Worttrennzeichen verschwunden. Sie haben nur noch eine Liste von Wörtern.

Kombinieren Sie dies mit der echo Dokumentation (ein bash interner Befehl), und Sie werden sehen, warum die Leerzeichen ausgegeben werden:

echo [-neE] [arg ...]: Die durch Leerzeichen getrennten Argumente, gefolgt von einer neuen Zeile, ausgeben.

Wenn Sie echo "$x" verwenden, wird die gesamte x -Variable zu einem einzelnen Wort gemäß bash gezwungen, daher wird es nicht aufgeteilt. Das können Sie sehen mit:

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

Hier gibt die Funktion count einfach die Anzahl der angegebenen Argumente aus. Die Varianten 1 2 3 und a b c d zeigen dies in Aktion.

Dann versuchen wir es mit den beiden Variationen der Variablen x. Das eine ohne Anführungszeichen zeigt, dass es vier Wörter gibt, "test", "1", "test" und "2". Das Hinzufügen der Anführungszeichen ergibt ein einzelnes Wort "test 1\ntest 2".

146
paxdiablo

Dies liegt an IFS (Internal Field Separator) Variable, die Zeilenumbrüche enthält. 

$ cat xx1
1
2

$ A=`cat xx1`
$ echo $A
1 2

$ echo "|$IFS|"
|       
|

Eine Problemumgehung besteht darin, IFS vorübergehend nicht auf die neue Zeile zu setzen:

$ IFSBAK=$IFS
$ IFS=" "
$ A=`cat xx1` # Can use $() as well
$ echo $A
1
2
$ IFS=$IFSBAK

Um diese schreckliche Änderung für IFS zu REVERTEN:

IFS=$IFSBAK
8
DVK

Bash -ge 4 verfügt über eine eingebaute Map-Datei, um Zeilen aus der Standardeingabe in eine Array-Variable zu lesen.

help mapfile 

mapfile < file.txt lines
printf "%s" "${lines[@]}"

mapfile -t < file.txt lines    # strip trailing newlines
printf "%s\n" "${lines[@]}" 

Siehe auch:

http://bash-hackers.org/wiki/doku.php/commands/builtin/mapfile

8
todd

Ihre Variable wird von testvar=$(cat test.txt) korrekt gesetzt. Um diese Variable anzuzeigen, die aus neuen Zeilenzeichen besteht, fügen Sie einfach doppelte Anführungszeichen ein, z.

echo "$testvar" 

Hier ist das vollständige Beispiel:

$ printf "test1\ntest2" > test.txt
$ testvar=$(<test.txt)
$ grep testvar <(set)
testvar=$'test1\ntest2'
$ echo "$testvar"
text1
text2
$ printf "%b" "$testvar"
text1
text2
2
kenorb

Nur wenn sich jemand für eine andere Option interessiert:

content=( $(cat test.txt) )

a=0
while [ $a -le ${#content[@]} ]
do
        echo ${content[$a]}
        a=$[a+1]
done
1
DerWilts

Das Dienstprogramm envdir bietet eine einfache Möglichkeit, dies zu tun. envdir verwendet Dateien zur Darstellung von Umgebungsvariablen. Dabei werden Dateinamen den Namen der Umgebungsvariablen und der Inhalt der Dateien den Werten der Umgebungsvariablen zugeordnet. Wenn der Dateiinhalt Zeilenumbrüche enthält, wird auch das env var verwendet.

Siehe https://pypi.python.org/pypi/envdir

0
Chris Johnson