Ich versuche herauszufinden, wie bash (force?) Variablen in einer Zeichenfolge (die aus einer Datei geladen wurde) erweitert.
Ich habe eine Datei namens "Something.txt" mit dem Inhalt:
hello $FOO world
Ich renne dann
export FOO=42
echo $(cat something.txt)
dies gibt zurück:
hello $FOO world
$ FOO wurde nicht erweitert, obwohl die Variable festgelegt wurde. Ich kann die Datei nicht auswerten oder beschaffen - da sie versucht, sie auszuführen (sie ist nicht so ausführbar wie sie ist - ich möchte nur die Zeichenfolge mit den interpolierten Variablen).
Irgendwelche Ideen?
eval
auf die Sicherheit von .eval
und es ist wichtig, sich der Auswirkungen bewusst zu sein.Antworten:
Ich stolperte über das, was ich für DIE Antwort auf diese Frage halte: den
envsubst
Befehl.Falls es in Ihrer Distribution noch nicht verfügbar ist, finden Sie es in der
GNU-Paket
gettext
.@ Rockallite - Ich habe ein kleines Wrapper-Skript geschrieben, um das Problem '\ $' zu lösen.
(Übrigens gibt es eine "Funktion" von envsubst, die unter https://unix.stackexchange.com/a/294400/7088 erläutert wird nur einige der Variablen in der Eingabe zu erweitern, aber ich stimme zu, dass es viel mehr ist, den Ausnahmen zu entkommen praktisch.)
Hier ist mein Skript:
quelle
$
) behandelt, z. B.echo '\$USER' | envsubst
wird der aktuelle Benutzername mit einem vorangestellten Schrägstrich ausgegeben, nicht$USER
.brew link --force gettext
Viele der Antworten mit
eval
undecho
Art der Arbeit, brechen aber bei verschiedenen Dingen ab, wie z. B. mehreren Zeilen, dem Versuch, Shell-Meta-Zeichen zu entkommen, innerhalb der Vorlage, die nicht durch Bash erweitert werden soll, usw.Ich hatte das gleiche Problem und schrieb diese Shell-Funktion, die, soweit ich das beurteilen kann, alles richtig handhabt. Aufgrund der Befehlsersetzungsregeln von bash werden immer noch nur nachgestellte Zeilenumbrüche aus der Vorlage entfernt, aber ich habe nie festgestellt, dass dies ein Problem ist, solange alles andere intakt bleibt.
Sie können es beispielsweise so verwenden, mit einem
parameters.cfg
Shell-Skript, das nur Variablen festlegt, undtemplate.txt
einer Vorlage, die diese Variablen verwendet:In der Praxis verwende ich dies als eine Art leichtes Vorlagensystem.
quelle
eval
Fallstricke. Versuchen Sie,; $(eval date)
am Ende einer Zeile in der Eingabedatei hinzuzufügen, und derdate
Befehl wird ausgeführt .Du kannst es versuchen
quelle
echo -e "$(eval "echo -e \"`<something.txt`\"")"
Sie diese Option, wenn neue Zeilen beibehalten werden sollen.template.txt
Text ist. Diese Operation ist gefährlich, da sie Befehle ausführt (auswertet), wenn dies der Fall ist.Sie möchten nicht jede Zeile drucken, sondern sie auswerten , damit Bash Variablensubstitutionen durchführen kann.
Siehe
help eval
oder das Bash Handbuch für weitere Informationen.quelle
eval
ist gefährlich ; Sie werden nicht nur$varname
erweitert (wie Sie es tun würdenenvsubst
), sondern$(rm -rf ~)
auch.Ein anderer Ansatz (der icky scheint, aber ich setze ihn trotzdem hier):
Schreiben Sie den Inhalt von Something.txt in eine temporäre Datei mit einer Echo-Anweisung:
Geben Sie es dann wieder in eine Variable ein:
und das $ RESULT wird alles erweitern. Aber es scheint so falsch!
quelle
Wenn Sie nur möchten, dass die Variablenreferenzen erweitert werden (ein Ziel, das ich für mich selbst hatte), können Sie Folgendes tun.
(Die maskierten Anführungszeichen um $ content sind hier der Schlüssel)
quelle
eval "echo \"$$contents\""
Folgende Lösung:
ermöglicht das Ersetzen definierter Variablen
Lässt unveränderte Variablen Platzhalter, die nicht definiert sind. Dies ist besonders nützlich bei automatisierten Bereitstellungen.
unterstützt das Ersetzen von Variablen in folgenden Formaten:
${var_NAME}
$var_NAME
meldet, welche Variablen in der Umgebung nicht definiert sind, und gibt in solchen Fällen einen Fehlercode zurück
quelle
Wenn something.txt hat nur eine Linie, eine
bash
Methode, (eine kürzere Version von Michael Neale „ekligen“ Antwort ), unter Verwendung von Verfahren und Befehlsersetzung :Ausgabe:
Beachten Sie, dass dies
export
nicht benötigt wird.Wenn something.txt hat eine oder mehr Linien, GNU bewertet Methode:
sed
e
quelle
sed
Bewertung am besten für meinen Zweck geeignet. Ich musste Skripte aus Vorlagen erstellen, deren Werte aus Variablen stammen, die in eine andere Konfigurationsdatei exportiert wurden. Es behandelt das ordnungsgemäße Escapezeichen für die Befehlserweiterung, z. B. das Einfügen\$(date)
in die Vorlage, um$(date)
in die Ausgabe zu gelangen . Vielen Dank!quelle
quelle
envsubst
ist eine großartige Lösung (siehe Antwort von LenW), wenn der Inhalt, den Sie ersetzen, eine "angemessene" Länge hat.In meinem Fall musste ich den Inhalt einer Datei ersetzen, um den Variablennamen zu ersetzen.
envsubst
erfordert, dass der Inhalt als Umgebungsvariablen exportiert wird, und bash hat ein Problem beim Exportieren von Umgebungsvariablen, die mehr als ein Megabyte oder so sind.awk Lösung
Verwendung der Lösung von cuonglm aus einer anderen Frage:
Diese Lösung funktioniert auch für große Dateien.
quelle
Folgendes funktioniert:
bash -c "echo \"$(cat something.txt)"\"
quelle
$foo
, sondern auch unsichere Erweiterungen ausgeführt$(rm -rf ~)
.