Ich möchte eine Datei lesen und in einer Variablen speichern, aber ich muss die Variable behalten und nicht nur die Datei ausdrucken. Wie kann ich das machen? Ich habe dieses Skript geschrieben, aber es ist nicht ganz das, was ich brauchte:
#!/bin/sh
while read LINE
do
echo $LINE
done <$1
echo 11111-----------
echo $LINE
In meinem Skript kann ich den Dateinamen als Parameter angeben. Wenn die Datei beispielsweise "aaaa" enthält, wird Folgendes ausgedruckt:
aaaa
11111-----
Dies druckt die Datei jedoch nur auf dem Bildschirm aus und ich möchte sie in einer Variablen speichern! Gibt es eine einfache Möglichkeit, dies zu tun?
cat
oder$(<someFile)
führen zu einer unvollständigen Ausgabe (die Größe ist geringer als die tatsächliche Datei).Antworten:
Im plattformübergreifenden kleinsten gemeinsamen Nenner verwenden
sh
Sie:In
bash
oderzsh
, um eine ganze Datei in eine Variable einzulesen, ohne sie aufzurufencat
:Das Aufrufen
cat
inbash
oder umzsh
eine Datei zu schlürfen wäre in Betracht gezogen wird Useless Verwendung von Cat .Beachten Sie, dass es nicht erforderlich ist, die Befehlsersetzung anzugeben, um Zeilenumbrüche beizubehalten.
Siehe: Bash Hacker's Wiki - Befehlsersetzung - Spezialitäten .
quelle
value="`cat config.txt`"
und wäre esvalue="$(<config.txt)"
nicht sicherer, wenn config.txt Leerzeichen enthält?cat
wie oben nicht immer als nutzlose Verwendung von angesehen wirdcat
. Zum Beispiel< invalid-file 2>/dev/null
wird in einer Fehlermeldung, die nicht weitergeleitet werden/dev/null
, währendcat invalid-file 2>/dev/null
korrekt weitergeleitet bekommt/dev/null
.value=$(<config.txt)
das gut, abervalue = $(<config.txt)
schlecht ist. Achten Sie auf diese Räume.Wenn Sie die gesamte Datei in eine Variable einlesen möchten:
Wenn Sie es Zeile für Zeile lesen möchten:
quelle
echo "$value"
. Andernfalls führt die Shell eine Whitespace-Tokenisierung und eine Platzhaltererweiterung für den Wert durch.read -r
statt nurread
- immer, es sei denn, Sie benötigen speziell das seltsame Legacy-Verhalten, auf das Sie anspielen.Zwei wichtige Fallstricke
die bisher von anderen Antworten ignoriert wurden:
Nachfolgendes Entfernen von Zeilenumbrüchen aus der Befehlserweiterung
Dies ist ein Problem für:
Typ Lösungen, aber nicht für
read
basierte Lösungen.Die Befehlserweiterung entfernt nachgestellte Zeilenumbrüche:
Ausgänge:
Dies unterbricht die naive Methode zum Lesen aus Dateien:
POSIX-Problemumgehung: Fügen Sie der Befehlserweiterung ein zusätzliches Zeichen hinzu und entfernen Sie es später:
Ausgänge:
Fast POSIX-Problemumgehung: ASCII-Codierung. Siehe unten.
NUL Zeichenentfernung
Es gibt keine vernünftige Bash-Methode, um NUL-Zeichen in Variablen zu speichern .
Dies wirkt sich sowohl auf die Erweiterung als auch auf die
read
Lösungen aus, und ich kenne keine gute Problemumgehung dafür.Beispiel:
Ausgänge:
Ha, unser NUL ist weg!
Problemumgehungen:
ASCII-Codierung. Siehe unten.
Verwenden Sie Bash-Erweiterungsliterale
$""
:Funktioniert nur für Literale und ist daher nicht zum Lesen aus Dateien geeignet.
Problemumgehung für die Fallstricke
Speichern Sie eine uuencode base64-codierte Version der Datei in der Variablen und dekodieren Sie sie vor jeder Verwendung:
Ausgabe:
uuencode und udecode sind POSIX 7, aber standardmäßig nicht in Ubuntu 12.04 (
sharutils
Paket) ... Ich sehe keine POSIX 7-Alternative für die Bash-Prozess-<()
Ersetzungserweiterung, außer in eine andere Datei zu schreiben ...Dies ist natürlich langsam und unpraktisch, daher lautet die eigentliche Antwort: Verwenden Sie Bash nicht, wenn die Eingabedatei NUL-Zeichen enthalten kann.
quelle
S="$(printf "\\\'\"")"; echo $S
. Ausgabe :\'"
. So funktioniert es =)$()
Erweiterung. Mein Beispiel zeigt, dass die$()
Erweiterung mit funktioniert\'"
.das funktioniert bei mir:
v=$(cat <file_path>) echo $v
quelle
Wie Ciro Santilli mit Befehlsersetzungen feststellt , werden nachfolgende Zeilenumbrüche gelöscht. Die Problemumgehung beim Hinzufügen von nachgestellten Zeichen ist großartig, aber nachdem ich sie einige Zeit verwendet hatte, entschied ich, dass ich eine Lösung brauchte, die überhaupt keine Befehlsersetzung verwendete.
Mein Ansatz verwendet jetzt
read
zusammen mit demprintf
eingebauten-v
Flag , um den Inhalt von stdin direkt in eine Variable einzulesen.Dies unterstützt Eingaben mit oder ohne nachgestellte Zeilenumbrüche.
Anwendungsbeispiel:
quelle
_contents="${_contents}${_line}\n "
, um Zeilenumbrüche zu erhalten.$'\n'
? Das ist notwendig, sonst hängen Sie Literale\
undn
Zeichen an. Ihr Codeblock hat am Ende auch einen zusätzlichen Platz, nicht sicher, ob dies beabsichtigt ist, aber er würde jede nachfolgende Zeile mit einem zusätzlichen Leerzeichen einrücken.Sie können mit der for-Schleife jeweils auf 1 Zeile zugreifen
Kopieren Sie den gesamten Inhalt in die Datei (z. B. line.sh). Ausführen
quelle
for
Schleife durchläuft keine Zeilen, sondern Wörter. Im Fall von/etc/passwd
kommt es vor, dass jede Zeile nur ein Wort enthält. Andere Dateien können jedoch mehrere Wörter pro Zeile enthalten.