Ich habe mehrere Textdateien, in die ich Shell-Variablen eingeführt habe (z. B. $ VAR1 oder $ VAR2).
Ich möchte diese Dateien (einzeln) nehmen und in neuen Dateien speichern, in denen alle Variablen ersetzt worden wären.
Zu diesem Zweck habe ich das folgende Shell-Skript verwendet (in StackOverflow gefunden):
while read line
do
eval echo "$line" >> destination.txt
done < "source.txt"
Dies funktioniert sehr gut bei sehr einfachen Dateien.
Bei komplexeren Dateien führt der Befehl "eval" jedoch zu viel aus:
Zeilen, die mit "#" beginnen, werden übersprungen
Das Parsen von XML-Dateien führt zu unzähligen Fehlern
Gibt es einen besseren Weg, dies zu tun? (im Shell-Skript ... Ich weiß, dass dies zum Beispiel mit Ant leicht gemacht werden kann)
Mit freundlichen Grüßen
envsubst
ist Teil von GNU gettextsource.txt
jede enthält$
Zeichen außerhalb der variablen Expansion,envsubst
wird diese auch ersetzen und es gibt keine Möglichkeit , das zu entkommen$
. Häufige (hässliche) Problemumgehung istexport DOLLAR="$"
.In Bezug auf Antwort 2 haben Sie bei der Erörterung von envsubst gefragt:
Die Antwort ist, dass Sie einfach Ihre Variablen exportieren müssen, bevor Sie aufrufen
envsubst
.Sie können die Variablenzeichenfolgen, die Sie in der Eingabe ersetzen möchten, auch mithilfe des
envsubst
SHELL_FORMAT
Arguments einschränken (um zu vermeiden, dass eine Zeichenfolge in der Eingabe unbeabsichtigt durch einen gemeinsamen Shell-Variablenwert ersetzt wird - z$HOME
. B. ).Zum Beispiel:
export VAR1='somevalue' VAR2='someothervalue' MYVARS='$VAR1:$VAR2' envsubst "$MYVARS" <source.txt >destination.txt
Werden alle Instanzen ersetzen
$VAR1
und$VAR2
(und nurVAR1
undVAR2
) insource.txt
mit'somevalue'
und'someothervalue'
jeweils.quelle
'
, die zum Setzen verwendet werden,MYVARS
sind entscheidendexport
,envsubst
oder ein Interleaving-Befehl fehlschlagen kann, wenn der zu ersetzende Text groß ist. Referenz.SHELL_FORMAT
Arguments (dh"$MYVARS"
) dazu führt, dass alle exportierten Variablen ersetzt werden. Wenn Sie das brauchen, dann machen Sie sich keine Sorgen.Ich weiß, dass dieses Thema alt ist, aber ich habe eine einfachere Arbeitslösung, ohne die Variablen zu exportieren. Kann ein Oneliner sein, aber ich ziehe es vor, mit dem
\
Online-Ende zu teilen .var1='myVar1'\ var2=2\ var3=${var1}\ envsubst '$var1,$var3' < "source.txt" > "destination.txt" # ^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^ # define which to replace input output
Die Variablen müssen in derselben Zeile definiert werden
envsubst
, um als Umgebungsvariablen betrachtet zu werden.Das
'$var1,$var3'
ist optional, um nur die angegebenen zu ersetzen. Stellen Sie sich eine Eingabedatei vor,${VARIABLE_USED_BY_JENKINS}
die nicht ersetzt werden soll.quelle
$ export MY_ENV_VAR=congratulation
$MY_ENV_VAR
Sie können auch alle anderen von Ihrem System definierten ENV-Variablen wie (unter Linux) $ TERM, $ SHELL, $ HOME ... verwenden.
$ envsubst "`printf '${%s} ' $(sh -c "env|cut -d'=' -f1")`" < in.txt > out.txt
und Sie sollten "Glückwunsch" sehen.
quelle
Wenn Sie wirklich nur bash (und sed) verwenden möchten, würde ich jede Ihrer Umgebungsvariablen (wie von
set
im posix-Modus zurückgegeben) durchgehen und daraus eine Reihe von-e 'regex'
for sed erstellen , die mit a abgeschlossen sind-e 's/\$[a-zA-Z_][a-zA-Z0-9_]*//g'
, und dann all das an übergeben sed.Perl würde einen besseren Job machen, Sie haben Zugriff auf die Umgebungsvariablen als Array und können ausführbare Ersetzungen durchführen, sodass Sie nur einmal mit einer Umgebungsvariablen übereinstimmen.
quelle
perl -pi -e 'foreach $key(sort keys %ENV){ s/\$$key/$ENV{$key}/g}' "$main_tf_file"
Eigentlich müssen Sie Ihre ändern
read
,read -r
wodurch Backslashes ignoriert werden.Außerdem sollten Sie Anführungszeichen und Backslashes vermeiden. Damit
while read -r line; do line="${line//\\/\\\\}" line="${line//\"/\\\"}" line="${line//\`/\\\`}" eval echo "\"$line\"" done > destination.txt < source.txt
Trotzdem eine schreckliche Möglichkeit, Expansion zu betreiben.
quelle
Exportieren Sie alle benötigten Variablen und verwenden Sie dann einen Perl-Onliner
TEXT=$(echo "$TEXT"|perl -wpne 's#\${?(\w+)}?# $ENV{$1} // $& #ge;')
Dadurch werden alle in TEXT vorhandenen ENV-Variablen durch tatsächliche Werte ersetzt. Zitate bleiben auch erhalten :)
quelle
Wenn Sie möchten, dass env-Variablen in Ihren Quelldateien ersetzt werden, während alle nicht env-Variablen unverändert bleiben, können Sie den folgenden Befehl verwenden:
envsubst "$(printf '${%s} ' $(env | sed 's/=.*//'))" < source.txt > destination.txt
Die Syntax zum Ersetzen nur bestimmter Variablen wird hier erläutert . Der obige Befehl verwendet eine Unter-Shell, um alle definierten Variablen aufzulisten und sie dann an die zu übergeben
envsubst
Wenn also eine definierte env-Variable aufgerufen
$NAME
wird und Ihresource.txt
Datei folgendermaßen aussieht:Hello $NAME Your balance is 123 ($USD)
Das
destination.txt
wird sein:Hello Arik Your balance is 123 ($USD)
Beachten Sie, dass das
$NAME
ersetzt wird und das$USD
unberührt bleibtquelle
Rufen Sie die Perl-Binärdatei im Such- und Ersetzungsmodus pro Zeile (the
-pi
) auf, indem Sie den Perl-Code (the-e
) in einfachen Anführungszeichen ausführen , der über die Schlüssel des speziellen%ENV
Hashs iteriert , der die exportierten Variablennamen als Schlüssel und die exportierten Variablenwerte als enthält Die Werte der Schlüssel und für jede einfache Iteration ersetzen Sie eine Zeichenfolge, die a enthält,$<<key>>
durch ihre<<value>>
.perl -pi -e 'foreach $key(sort keys %ENV){ s/\$$key/$ENV{$key}/g}' file
Vorsichtsmaßnahme: In Fällen, in denen zwei oder mehr Vars mit derselben Zeichenfolge beginnen, ist eine zusätzliche Logikbehandlung erforderlich ...
quelle
envsubst
scheint genau wie etwas, das ich verwenden wollte, aber-v
Option hat mich ein bisschen überrascht.Während
envsubst < template.txt
es gut funktionierte, funktionierte das gleiche mit Option-v
nicht:Wie ich schrieb, funktionierte das nicht:
Ich musste das tun, damit es funktioniert:
Vielleicht hilft es jemandem.
quelle