Ich möchte die Ausgabe einer "Vorlagendatei" in MySQL weiterleiten, wobei die Datei Variablen wie " ${dbName}
eingestreut" enthält. Was ist das Befehlszeilenprogramm, um diese Instanzen zu ersetzen und die Ausgabe auf die Standardausgabe zu übertragen?
bash
command-line
text-processing
templating
Dana die Gesunde
quelle
quelle
cat
. Alles was Sie brauchen istsed -e "s/\${i}/1/" -e "s/\${word}/dog/" template.text
.sed
wird ein maskierter Text erwartet, was ein Ärger ist.Aktualisieren
Hier ist eine Lösung von yottatsa zu einer ähnlichen Frage, die nur Variablen wie $ VAR oder $ {VAR} ersetzt und ein kurzer Einzeiler ist
Natürlich, wenn ich und Wort in Ihrer Umgebung sind, dann ist es einfach
Auf meinem Mac scheint es als Teil von gettext und von MacGPG2 installiert worden zu sein
Alte Antwort
Hier ist eine Verbesserung der Lösung von Mogsie in einer ähnlichen Frage. Meine Lösung erfordert nicht, dass Sie doppelte Anführungszeichen eskalieren, Mogsie's, aber er ist ein Einzeiler!
Die Kraft auf diesen beiden Lösungen ist , dass Sie nur ein paar Arten von Shell - Erweiterungen bekommen, die normalerweise nicht $ auftreten ((...)), `...` und $ (...), obwohl Backslash ist ein Escape-Zeichen hier, aber Sie müssen sich keine Sorgen machen, dass das Parsen einen Fehler aufweist und mehrere Zeilen in Ordnung sind.
quelle
envsubst
finde , dass das Bare nicht funktioniert, wenn Ihre Envars nicht exportiert werden.envsubst
erkennt, wie der Name schon sagt, nur Umgebungsvariablen , keine Shell- Variablen. Es ist auch erwähnenswert, dassenvsubst
es sich um ein GNU- Dienstprogramm handelt, das nicht auf allen Plattformen vorinstalliert oder verfügbar ist.Verwenden Sie
/bin/sh
. Erstellen Sie ein kleines Shell-Skript, das die Variablen festlegt, und analysieren Sie dann die Vorlage mithilfe der Shell. So (bearbeiten, um Zeilenumbrüche korrekt zu behandeln):Datei template.txt:
Datei script.sh:
Ausgabe:
quelle
bash
Befehle in der Eingabe werden ausgeführt. Wenn die Vorlage lautet: "Die Wörter sind; rm -rf $ HOME", verlieren Sie Dateien.read
Befehl schneidet wie geschrieben führende und nachfolgende Leerzeichen aus jeder Zeile ab und "isst"\
Zeichen. (C) verwendet dies nur, wenn Sie es vollständig verwenden Vertrauen oder steuern Sie die Eingabe, da in die Eingabe eingebettete Befehlssubstitutionen (`…`
oder$(…)
) die Ausführung beliebiger Befehle aufgrund der Verwendung von ermöglicheneval
. Schließlich besteht eine geringe Wahrscheinlichkeit, dassecho
der Zeilenanfang mit einer der Befehlszeilenoptionen verwechselt wird.m4
Angesichts des jüngsten Interesses habe ich erneut darüber nachgedacht, und ich denke, dass das Tool, an das ich ursprünglich gedacht habe , der Makroprozessor für Autotools war. Anstelle der ursprünglich angegebenen Variablen würden Sie also Folgendes verwenden:quelle
envsubst
für diese einfache Verwendung zum Ersetzen / Vorlagen von Variablen verwenden, wie in anderen Antworten erwähnt.m4
ist ein großartiges Werkzeug, aber es ist ein vollwertiger Präprozessor mit viel mehr Funktionen und damit Komplexität, die möglicherweise nicht benötigt werden, wenn Sie einfach einige Variablen ersetzen möchten.template.txt
data.sh
parser.sh
parsed_file.txt
quelle
`…`
oder$(…)
) die Ausführung beliebiger Befehle aufgrund der Verwendung voneval
und die direkte Ausführung von Shell-Code aufgrund der Verwendung von ermöglichensource
. Außerdem werden doppelte Anführungszeichen in der Eingabe stillschweigend verworfen undecho
können den Zeilenanfang mit einer der Befehlszeilenoptionen verwechseln.Hier ist eine robuste Bash-Funktion , die trotz Verwendung
eval
sicher sein sollte.Alle
${varName}
Variablenreferenzen im Eingabetext werden basierend auf den Variablen der aufrufenden Shell erweitert.Nichts anderes wird erweitert: weder Variablenreferenzen, deren Namen nicht eingeschlossen sind
{...}
(z. B.$varName
), noch Befehlssubstitutionen ($(...)
und Legacy-Syntax`...`
) noch arithmetische Substitutionen ($((...))
und Legacy-Syntax)$[...]
).Um a
$
als wörtlich zu behandeln ,\
entkomme es; z.B:\${HOME}
Beachten Sie, dass Eingaben nur über stdin akzeptiert werden .
Beispiel:
Funktionsquellcode:
Die Funktion wird davon ausgegangen , dass keine
0x1
,0x2
,0x3
, und0x4
Steuerzeichen in der Eingabe vorhanden sind, weil diese Zeichen. werden intern verwendet - da die Funktion Text verarbeitet , sollte dies eine sichere Annahme sein.quelle
eval
es ziemlich sicher zu bedienen."
richtig!)${FOO:-bar}
oder nur etwas ausgeben können, wenn es gesetzt ist -${HOME+Home is ${HOME}}
. Ich vermute, mit einer kleinen Erweiterung könnte es auch Exit-Codes für fehlende Variablen zurückgeben${FOO?Foo is missing}
, aber derzeit hat tldp.org/LDP/abs/html/parameter-substitution.html keine Liste davon, wenn das hilftErstellen
rendertemplate.sh
:Und
template.tmpl
:Rendern Sie die Vorlage:
quelle
$(rm -rf ~)
, führen Sie dies als Code aus.eval "echo \"$(cat $1)\""
Funktioniert super !Hier ist meine Lösung mit Perl basierend auf der vorherigen Antwort, ersetzt Umgebungsvariablen:
quelle
Wenn Sie offen für Perl sind, wäre das mein Vorschlag. Obwohl es wahrscheinlich einige Sed- und / oder AWK- Experten gibt, die wahrscheinlich wissen, wie man das viel einfacher macht. Wenn Sie eine komplexere Zuordnung mit mehr als nur dbName für Ihre Ersetzungen haben, können Sie diese ziemlich einfach erweitern, aber Sie können sie zu diesem Zeitpunkt genauso gut in ein Standard-Perl-Skript einfügen.
Ein kurzes Perl-Skript, um etwas etwas komplizierteres zu tun (mehrere Schlüssel verarbeiten):
Wenn Sie das obige Skript als Ersetzungsskript bezeichnen, kann es wie folgt verwendet werden:
quelle
Hier ist eine Möglichkeit, die Shell dazu zu bringen, die Ersetzung für Sie durchzuführen, als ob der Inhalt der Datei stattdessen zwischen doppelten Anführungszeichen eingegeben würde.
Am Beispiel von template.txt mit Inhalten:
Die folgende Zeile bewirkt, dass die Shell den Inhalt von template.txt interpoliert und das Ergebnis in standard out schreibt.
Erläuterung:
i
undword
werden als Umgebungsvariablen übergeben, die zur Ausführung vonsh
.sh
führt den Inhalt der übergebenen Zeichenfolge aus.echo "
' + "$(cat template.txt)
" + '"
'"
, wird "$(cat template.txt)
" die Ausgabe voncat template.txt
.sh -c
:echo "The number is ${i}\nThe word is ${word}"
,i
undword
sind die angegebenen Umgebungsvariablen.quelle
'$(rm -rf ~)'$(rm -rf ~)
stimmen die wörtlichen Anführungszeichen in der Vorlagendatei mit denen überein, die Sie vor der Erweiterung hinzugefügt haben.'$(echo a)'$(echo a)
. Es produziert'a'a
. Die Hauptsache, die passiert, ist, dass das erste imecho a
Inneren'
ausgewertet wird, was möglicherweise nicht das ist, was Sie erwarten, da es sich in befindet'
, aber dasselbe Verhalten wie das Einfügen'
in eine"
Zeichenfolge in Anführungszeichen."
Zeichenfolge mit Anführungszeichen (einschließlich$(...)
) ist der Punkt.${varname}
weiteren Erweiterungen mit höherem Sicherheitsrisiko fragen .echo "
einfügentemplate.txt
, teilen Sie sich in eine Zeichenfolge in einfachen Anführungszeichen auf , gefolgt von einer Zeichenfolge in doppelten Anführungszeichen mit den Literal-Contetns von , gefolgt von einer weiteren Literal-Zeichenfolge"
, die alle zu einem einzigen Argument verkettet sind, an das übergeben wirdsh -c
. Sie haben Recht, dass das'
nicht übereinstimmen kann (da es von der äußeren Hülle verbraucht wurde, anstatt an die innere übergeben zu werden), aber das"
kann sicher, so dass eine VorlageGotcha"; rm -rf ~; echo "
ausgeführt werden kann, die enthält .file.tpl:
script.sh:
quelle
\$(date)
while IFS= read -r line; do
alsread
Befehl, andernfalls entfernen Sie führende und nachfolgende Leerzeichen aus jeder Eingabezeile. Außerdemecho
könnte der Zeilenanfang mit einer der Befehlszeilenoptionen verwechselt werden, daher ist es besser, ihn zu verwendenprintf '%s\n'
. Schließlich ist es sicherer, doppelte Anführungszeichen zu setzen${1}
.Ich würde vorschlagen, etwas wie Sigil zu verwenden : https://github.com/gliderlabs/sigil
Es ist zu einer einzigen Binärdatei kompiliert, sodass die Installation auf Systemen äußerst einfach ist.
Dann können Sie einen einfachen Einzeiler wie den folgenden erstellen:
Dies ist viel sicherer als
eval
und einfacher als die Verwendung von Regex odersed
quelle
cat
und<my-file.conf.template
stattdessen zu verwenden, damit Siesigil
anstelle eines FIFO ein echtes Dateihandle geben.Ich habe diesen Thread gefunden, als ich mich das Gleiche gefragt habe. Es hat mich dazu inspiriert (vorsichtig mit den Backticks)
quelle
$(cat file)
is$(< file)
eval echo "\"$(cat FILE)\""
aber das kann immer noch zu kurz kommen, da doppelte Anführungszeichen in der Eingabe verworfen werden.`…`
oder$(…)
) die Ausführung beliebiger Befehle aufgrund der Verwendung von ermöglicheneval
.Viele Möglichkeiten hier, aber ich dachte, ich würde meine auf den Haufen werfen. Es basiert auf Perl, zielt nur auf Variablen der Form $ {...} ab, verwendet die zu verarbeitende Datei als Argument und gibt die konvertierte Datei auf stdout aus:
Natürlich bin ich nicht wirklich eine Perl-Person, daher kann es leicht zu einem schwerwiegenden Fehler kommen (funktioniert aber für mich).
quelle
Env::import();
Zeile löschen - der Import wird durch impliziertuse
. Außerdem empfehle ich, nicht zuerst die gesamte Ausgabe im Speicher aufzubauen: Verwenden Sie einfachprint;
statt$text .= $_;
innerhalb der Schleife und lassen Sie den Post-Loop-print
Befehl fallen.Dies kann in Bash selbst erfolgen, wenn Sie die Kontrolle über das Konfigurationsdateiformat haben. Sie müssen nur die Konfigurationsdatei als Quelle (".") Geben, anstatt sie zu unterteilen. Dadurch wird sichergestellt, dass die Variablen im Kontext der aktuellen Shell erstellt werden (und weiterhin vorhanden sind) und nicht in der Subshell (wobei die Variable beim Beenden der Subshell verschwindet).
Wenn Ihre Konfigurationsdatei kein Shell-Skript sein kann, können Sie sie vor der Ausführung einfach "kompilieren" (die Kompilierung hängt von Ihrem Eingabeformat ab).
In Ihrem speziellen Fall könnten Sie Folgendes verwenden:
Dann leiten Sie die Ausgabe von go.bash an MySQL und voila weiter, hoffentlich zerstören Sie Ihre Datenbank nicht :-).
quelle
go.bash
) sprechen , haben Sie das falsche Ende des Sticks - sie sind nicht Teil der Lösung, sondern nur eine Möglichkeit zu zeigen, dass die Variablen vorhanden sind richtig eingestellt.Perl-Bearbeitung von potenziell mehreren Dateien mit Backups.
quelle