766 Stimmen

Wie liest man eine Datei in eine Variable in der Shell?

Ich möchte eine Datei lesen und sie 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 brauche:

#!/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 also beispielsweise "aaaa" enthält, würde das Skript Folgendes ausgeben:

aaaa
11111-----

Aber das gibt die Datei nur auf dem Bildschirm aus, und ich möchte sie in einer Variablen speichern! Gibt es eine einfache Möglichkeit, dies zu tun?

1549voto

Alan Gutierrez Punkte 14109

Im plattformübergreifenden, kleinsten gemeinsamen Nenner sh Sie verwenden:

#!/bin/sh
value=`cat config.txt`
echo "$value"

En bash o zsh um eine ganze Datei in eine Variable zu lesen, ohne den Aufruf cat :

#!/bin/bash
value=$(<config.txt)
echo "$value"

Aufrufen von cat in bash o zsh eine Datei zu schlürfen, würde als eine Unnötige Verwendung der Katze .

Beachten Sie, dass es nicht notwendig ist, die Befehlssubstitution in Anführungszeichen zu setzen, um Zeilenumbrüche zu erhalten.

Siehe: Bash Hacker's Wiki - Befehlsersetzung - Spezialitäten .

121voto

Zwei wichtige Fallstricke

die in anderen Antworten bisher ignoriert wurden:

  1. Entfernen von nachgestellten Zeilenumbrüchen aus Befehlserweiterungen
  2. NUL-Zeichen entfernen

Entfernung von Zeilenumbrüchen aus der Befehlserweiterung

Dies ist ein Problem für die:

value="$(cat config.txt)"

Lösungen, nicht aber für read basierte Lösungen.

Bei der Befehlsexpansion werden nachfolgende Zeilenumbrüche entfernt:

S="$(printf "a\n")"
printf "$S" | od -tx1

Ausgänge:

0000000 61
0000001

Dadurch wird die naive Methode des Lesens von Dateien durchbrochen:

FILE="$(mktemp)"
printf "a\n\n" > "$FILE"
S="$(<"$FILE")"
printf "$S" | od -tx1
rm "$FILE"

POSIX-Umgehung: Fügen Sie ein zusätzliches Zeichen an die Befehlserweiterung an und entfernen Sie es später:

S="$(cat $FILE; printf a)"
S="${S%a}"
printf "$S" | od -tx1

Ausgänge:

0000000 61 0a 0a
0000003

Fast POSIX-Umgehung: ASCII-Kodierung. Siehe unten.

NUL-Zeichen entfernen

Es gibt keinen vernünftigen Bash-Weg, um NUL-Zeichen in Variablen zu speichern .

Dies betrifft sowohl die Expansion als auch die read Lösungen, und ich kenne keine gute Umgehung für dieses Problem.

Beispiel:

printf "a\0b" | od -tx1
S="$(printf "a\0b")"
printf "$S" | od -tx1

Ausgänge:

0000000 61 00 62
0000003

0000000 61 62
0000002

Ha, unser NUL ist weg!

Umgehungen:

  • ASCII-Kodierung. Siehe unten.

  • Bash-Erweiterung verwenden $"" Literale:

    S=$"a\0b"
    printf "$S" | od -tx1

    Funktioniert nur für Literale, also nicht für das Lesen aus Dateien.

Abhilfe für die Fallstricke

Speichern Sie eine uuencode base64 kodierte Version der Datei in der Variablen und dekodieren Sie sie vor jeder Verwendung:

FILE="$(mktemp)"
printf "a\0\n" > "$FILE"
S="$(uuencode -m "$FILE" /dev/stdout)"
uudecode -o /dev/stdout <(printf "$S") | od -tx1
rm "$FILE"

Ausgabe:

0000000 61 00 0a
0000003

uuencode und udecode sind POSIX 7 aber nicht in Ubuntu 12.04 standardmäßig ( sharutils Paket)... Ich sehe keine POSIX 7 Alternative für den Bash-Prozess <() Substitutionserweiterung außer dem Schreiben in eine andere Datei...

Das ist natürlich langsam und unbequem, also lautet die Antwort wohl: Verwenden Sie die Bash nicht, wenn die Eingabedatei NUL-Zeichen enthalten kann.

113voto

brain Punkte 2447

Wenn Sie die gesamte Datei in eine Variable einlesen wollen:

#!/bin/bash
value=`cat sources.xml`
echo $value

Wenn Sie ihn Zeile für Zeile lesen möchten:

while read line; do    
    echo $line    
done < file.txt

31voto

angelo.mastro Punkte 1241

Das funktioniert bei mir: v=$(cat <file_path>) echo $v

19voto

Léa Gris Punkte 14520

Mit bash können Sie read wie diese:

#!/usr/bin/env bash

{ IFS= read -rd '' value <config.txt;} 2>/dev/null

printf '%s' "$value"

Beachten Sie das:

  • Der letzte Zeilenumbruch bleibt erhalten.

  • El stderr wird zum Schweigen gebracht /dev/null durch Umleitung des gesamten Befehlsblocks, aber der Rückgabestatus des Lesebefehls bleibt erhalten, falls man Lesefehlerbedingungen behandeln musste.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X