Ich versuche, mehrere Zeilen in einer Bash-Variablen zu speichern, aber es scheint nicht zu funktionieren.
Wenn ich zum Beispiel /bin
eine Datei pro Zeile aufführe und darin speichere $LS
, übergebe ich $LS
als stdin an wc
immer 1:
$ ls -1 /bin | wc -l
134
$ LS=$(ls -1 /bin); wc -l <<< $LS
1
Wenn ich versuche, auf dem Bildschirm auszugeben, erhalte ich verschiedene Ergebnisse: echo
Druckt alle Zeilen in einer einzelnen Zeile, während printf
nur die erste Zeile gedruckt wird:
#!/bin/bash
LS=$(ls -1 /bin)
echo $LS
printf $LS
Eine Bash-Variable kann also mehrere Zeilen enthalten?
printf "%s\n" $LS
würde dies der Fall sein .wc
und anderen Befehlen:wc -l <<< "$LS"
printf '%s\n' "$LS"
wenn Sie Newline sehen möchten. Das ist eine falsche Eingabe, behoben!Die Zeilenumbrüche befinden sich in der Variablen.
LS=$(ls -1)
Setzt die VariableLS
auf die Ausgabe vonls -1
(diels
übrigens dieselbe Ausgabe erzeugt , außer wenn die Ausgabe an ein Terminal geht) abzüglich nachfolgender Zeilenumbrüche.Das Problem ist, dass Sie die Zeilenumbrüche entfernen, wenn Sie den Wert ausdrucken. In einem Shell-Skript
$LS
bedeutet dies nicht "den Wert der VariablenLS
", sondern "den Wert von nehmenLS
, ihn in Wörter aufteilenIFS
und jedes Wort als Glob-Muster interpretieren". Um den Wert von zu erhaltenLS
, müssen Sie schreiben"$LS"
oder allgemeiner$LS
zwischen doppelte Anführungszeichen setzen.echo "$LS"
Gibt den Wert von ausLS
, außer in einigen Shells, die Backslash-Zeichen interpretieren, und mit Ausnahme einiger Werte, die mit beginnen-
.printf "$LS"
Gibt den Wert vonLS
aus, solange er kein Prozent- oder Backslash-Zeichen enthält und (bei den meisten Implementierungen) nicht mit beginnt-
.LS
Verwenden Sie, um den Wert von genau zu druckenprintf %s "$LS"
. Wenn Sie am Ende einen Zeilenumbruch wünschen, verwenden Sieprintf '%s\n' "$LS"
.Beachten Sie, dass
$(ls)
dies im Allgemeinen nicht die Liste der Dateien im aktuellen Verzeichnis ist. Dies funktioniert nur, wenn Sie ausreichend zahme Dateinamen haben. Um die Liste der Dateinamen (außer Punktdateien) abzurufen, müssen Sie einen Platzhalter verwenden :*
. Das Ergebnis ist eine Liste von Zeichenfolgen, keine Zeichenfolge. Sie können sie daher keiner Zeichenfolgenvariablen zuweisen. Sie können eine Array-Variablefiles=(*)
in Shells verwenden, die sie unterstützen (ksh93, bash, zsh).Weitere Informationen finden Sie unter Warum verschluckt sich mein Shell-Skript an Leerzeichen oder anderen Sonderzeichen?
quelle
Das vorgenannte
ist die einzig richtige Lösung.
Lassen Sie mich zeigen, dass die anderen vorgeschlagenen Lösungen mit
echo
undprintf
einfach nicht richtig funktionieren:(Man kann auch mit
V=$(printf 'line0:\\n\\n\nline1.\n') printf '%s\n' "$V"
und Variationen testen .)Während
\n
die Dateinamen möglicherweise nicht so häufig vorkommen, speichern Sie siegit diff
in einer Variablen, und Ihre Chancen, auf Literal\n
zu stoßen, steigen dramatisch.quelle
ksh
undzsh
auch unterstützenprint -r -- "$LS"
undzsh
auch hatecho -E - $LS
.csh
hatecho $LS:q
jedoch das Zeilenumbruchzeichen nicht ausgegeben, wenn $ LS leer ist, und es ist in csh ziemlich schwierig, einen mehrzeiligen Wert in $ LS zu bekommen.