Wie ersetze ich $ {} Platzhalter in einer Textdatei?

162

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?

Dana die Gesunde
quelle

Antworten:

192

Sed !

Gegeben template.txt:

Die Nummer ist $ {i}
Das Wort ist $ {word}

wir müssen nur sagen:

sed -e "s/\${i}/1/" -e "s/\${word}/dog/" template.txt

Vielen Dank an Jonathan Leffler für den Tipp, mehrere -eArgumente an denselben sedAufruf zu übergeben.

Benutzer
quelle
13
Sie können diese beiden sed-Befehle zu einem kombinieren: sed -e "s / \ $ {i} / 1 /" -e "s / \ $ {word} / dog /"; das ist effizienter. Bei einigen Versionen von sed können bei etwa 100 solcher Vorgänge Probleme auftreten (Problem von vor Jahren - möglicherweise immer noch nicht wahr, aber Vorsicht vor HP-UX).
Jonathan Leffler
1
Danke Jonathan, genau das, wonach ich gesucht habe.
Dana the Sane
3
Kleiner Hinweis: Wenn "1" oder "Hund" im angegebenen Beispiel ein Dollarsymbol enthalten würde, müssten Sie es mit einem Backslash umgehen (andernfalls erfolgt kein Ersatz).
MatthieuP
9
Das brauchst du auch nicht cat. Alles was Sie brauchen ist sed -e "s/\${i}/1/" -e "s/\${word}/dog/" template.text.
HardlyKnowEm
3
Was ist, wenn der Ersatztext ein Passwort ist? In diesem Fall sedwird ein maskierter Text erwartet, was ein Ärger ist.
Jpbochi
176

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

i=32 word=foo envsubst < template.txt

Natürlich, wenn ich und Wort in Ihrer Umgebung sind, dann ist es einfach

envsubst < template.txt

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!

eval "cat <<EOF
$(<template.txt)
EOF
" 2> /dev/null

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.

plockc
quelle
6
Ich envsubstfinde , dass das Bare nicht funktioniert, wenn Ihre Envars nicht exportiert werden.
Toddius Zho
4
@ToddiusZho: Es gibt keine Umgebungsvariable, die nicht exportiert wird - genau das Exportieren macht eine Shell- Variable zu einer Umgebungsvariablen. envsubsterkennt, wie der Name schon sagt, nur Umgebungsvariablen , keine Shell- Variablen. Es ist auch erwähnenswert, dass envsubstes sich um ein GNU- Dienstprogramm handelt, das nicht auf allen Plattformen vorinstalliert oder verfügbar ist.
mklement0
2
Vielleicht kann man auch sagen, dass envsubst nur die eigenen Prozessumgebungsvariablen sieht, sodass "normale" Shell-Variablen, die Sie möglicherweise zuvor definiert haben (in separaten Zeilen), nicht von untergeordneten Prozessen geerbt werden, es sei denn, Sie "exportieren" sie. In meiner obigen Beispielverwendung von gettext ändere ich die geerbte gettext-Umgebung durch einen Bash-Mechanismus, indem ich sie dem Befehl
voranstelle
1
Ich habe eine Zeichenfolge mit $ HOME darin. Ich fand, dass $ HOME als Standard-Shell verwendet wird, stattdessen $ HOME als meine eigene / home / zw963, aber es scheint, als würde die Ersetzung von $ (cat / etc / hostname) nicht unterstützt. es entspricht also nicht vollständig meiner eigenen Nachfrage.
zw963
3
Vielen Dank für die "alte Antwort", da sie nicht nur Variablen erlaubt, sondern auch Shell-Befehle wie $ (ls -l)
Alek
46

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:

the number is ${i}
the word is ${word}

Datei script.sh:

#!/bin/sh

#Set variables
i=1
word="dog"

#Read in template one line at the time, and replace variables (more
#natural (and efficient) way, thanks to Jonathan Leffler).
while read line
do
    eval echo "$line"
done < "./template.txt"

Ausgabe:

#sh script.sh
the number is 1
the word is dog
Gnud
quelle
2
Warum nicht einfach: beim Lesen der Zeile; eval echo "$ line"; erledigt <./template.txt ??? Es ist nicht erforderlich, die gesamte Datei in den Speicher einzulesen, sondern sie nur durch intensiven Einsatz von Kopf und Schwanz zeilenweise auszuspucken. Aber die 'Bewertung' ist in Ordnung - es sei denn, die Vorlage enthält Shell-Zeichen wie Anführungszeichen.
Jonathan Leffler
16
Das ist sehr gefährlich! Alle bashBefehle in der Eingabe werden ausgeführt. Wenn die Vorlage lautet: "Die Wörter sind; rm -rf $ HOME", verlieren Sie Dateien.
Enzymm
1
@rzymek - denken Sie daran, er möchte diese Datei direkt in die Datenbank leiten. Anscheinend ist die Eingabe also vertrauenswürdig.
Gnud
4
@gnud Es gibt einen Unterschied zwischen dem Vertrauen in eine Datei, die ausreicht, um ihren Inhalt zu speichern, und dem Vertrauen, dass sie ausreicht, um alles auszuführen, was sie enthält.
Mark
3
Um die Einschränkungen zu beachten: (a) doppelte Anführungszeichen in der Eingabe werden stillschweigend verworfen, (b) der readBefehl 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öglichen eval. Schließlich besteht eine geringe Wahrscheinlichkeit, dass echoder Zeilenanfang mit einer der Befehlszeilenoptionen verwechselt wird.
mklement0
23

m4Angesichts 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:

$echo 'I am a DBNAME' | m4 -DDBNAME="database name"
Dana die Gesunde
quelle
1
Diese Lösung hat die wenigsten Nachteile der Antworten hier. Kennen Sie eine Möglichkeit, $ {DBNAME} anstelle von nur DBNAME zu ersetzen?
Jack Davidson
@JackDavidson Ich würde envsubstfür diese einfache Verwendung zum Ersetzen / Vorlagen von Variablen verwenden, wie in anderen Antworten erwähnt. m4ist 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.
Imiric
13

template.txt

Variable 1 value: ${var1}
Variable 2 value: ${var2}

data.sh

#!/usr/bin/env bash
declare var1="value 1"
declare var2="value 2"

parser.sh

#!/usr/bin/env bash

# args
declare file_data=$1
declare file_input=$2
declare file_output=$3

source $file_data
eval "echo \"$(< $file_input)\"" > $file_output

./parser.sh data.sh template.txt parsed_file.txt

parsed_file.txt

Variable 1 value: value 1
Variable 2 value: value 2
ChaPuZ
quelle
1
Wie an anderer Stelle erwähnt: Verwenden Sie diese Option nur, wenn Sie der Eingabe vollständig vertrauen oder sie steuern, da in die Eingabe eingebettete Befehlssubstitutionen ( `…` oder $(…)) die Ausführung beliebiger Befehle aufgrund der Verwendung von evalund die direkte Ausführung von Shell-Code aufgrund der Verwendung von ermöglichen source. Außerdem werden doppelte Anführungszeichen in der Eingabe stillschweigend verworfen und echokönnen den Zeilenanfang mit einer der Befehlszeilenoptionen verwechseln.
mklement0
Leider werden dadurch alle doppelten Anführungszeichen (") aus der Ergebnisdatei entfernt. Gibt es eine Möglichkeit, dasselbe zu tun, ohne die doppelten Anführungszeichen zu entfernen?
Ivaylo Slavov
Ich habe hier gefunden, wonach ich gesucht habe: stackoverflow.com/a/11050943/795158 ; Ich habe envsubst verwendet. Der Unterschied ist, dass die Vars exportiert werden müssen, was für mich in Ordnung war.
Ivaylo Slavov
wenn die Textdatei "` "oder". "enthält. , Substitude wird fehlschlagen.
Shuiqiang vor
12

Hier ist eine robuste Bash-Funktion , die trotz Verwendung evalsicher 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:

$ expandVarsStrict <<<'$HOME is "${HOME}"; `date` and \$(ls)' # only ${HOME} is expanded
$HOME is "/Users/jdoe"; `date` and $(ls)

Funktionsquellcode:

expandVarsStrict(){
  local line lineEscaped
  while IFS= read -r line || [[ -n $line ]]; do  # the `||` clause ensures that the last line is read even if it doesn't end with \n
    # Escape ALL chars. that could trigger an expansion..
    IFS= read -r -d '' lineEscaped < <(printf %s "$line" | tr '`([$' '\1\2\3\4')
    # ... then selectively reenable ${ references
    lineEscaped=${lineEscaped//$'\4'{/\${}
    # Finally, escape embedded double quotes to preserve them.
    lineEscaped=${lineEscaped//\"/\\\"}
    eval "printf '%s\n' \"$lineEscaped\"" | tr '\1\2\3\4' '`([$'
  done
}

Die Funktion wird davon ausgegangen , dass keine 0x1, 0x2, 0x3, und 0x4Steuerzeichen in der Eingabe vorhanden sind, weil diese Zeichen. werden intern verwendet - da die Funktion Text verarbeitet , sollte dies eine sichere Annahme sein.

mklement0
quelle
2
Dies ist eine der besten Antworten hier. Selbst bei der Verwendung ist evales ziemlich sicher zu bedienen.
Anubhava
1
Diese Lösung funktioniert mit JSON-Dateien! (Flucht "richtig!)
WBAR
2
Eine nette Sache mit dieser Lösung ist, dass Sie Standardeinstellungen für fehlende Variablen bereitstellen ${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 hilft
Stuart Moore
11

Erstellen rendertemplate.sh:

#!/usr/bin/env bash

eval "echo \"$(cat $1)\""

Und template.tmpl:

Hello, ${WORLD}
Goodbye, ${CHEESE}

Rendern Sie die Vorlage:

$ export WORLD=Foo
$ CHEESE=Bar ./rendertemplate.sh template.tmpl 
Hello, Foo
Goodbye, Bar
neu242
quelle
2
Dies entfernt Zeichenfolgen in doppelten Anführungszeichen
vrtx54234
Versucht: eval "echo $ (cat $ 1)" - ohne Anführungszeichen, und es hat bei mir funktioniert.
access_granted
2
Aus Sicherheitsgründen sind dies schlechte Nachrichten. Wenn Ihre Vorlage enthält $(rm -rf ~), führen Sie dies als Code aus.
Charles Duffy
eval "echo \"$(cat $1)\"" Funktioniert super !
dev devv
10

Hier ist meine Lösung mit Perl basierend auf der vorherigen Antwort, ersetzt Umgebungsvariablen:

perl -p -e 's/\$\{(\w+)\}/(exists $ENV{$1}?$ENV{$1}:"missing variable $1")/eg' < infile > outfile
Thomas
quelle
2
Das ist toll. Haben Sie nicht immer Perl, aber wenn Sie dies tun, ist dies einfach und unkompliziert.
Aaron McMillin
5

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.

perl -p -e 's/\$\{dbName\}/testdb/s' yourfile | mysql

Ein kurzes Perl-Skript, um etwas etwas komplizierteres zu tun (mehrere Schlüssel verarbeiten):

#!/usr/bin/env perl
my %replace = ( 'dbName' => 'testdb', 'somethingElse' => 'fooBar' );
undef $/;
my $buf = <STDIN>;
$buf =~ s/\$\{$_\}/$replace{$_}/g for keys %replace;
print $buf;

Wenn Sie das obige Skript als Ersetzungsskript bezeichnen, kann es wie folgt verwendet werden:

replace-script < yourfile | mysql
Beau Simensen
quelle
1
Funktioniert für einzelne Variablen, aber wie füge ich 'oder' für die anderen ein?
Dana the Sane
2
Es gibt viele Möglichkeiten, wie Sie dies mit Perl tun können, je nachdem, wie kompliziert und / oder sicher Sie dies tun möchten. Kompliziertere Beispiele finden Sie hier: perlmonks.org/?node_id=718936
Beau Simensen
3
Die Verwendung von Perl ist so viel sauberer als der Versuch, die Shell zu verwenden. Nehmen Sie sich Zeit, damit dies funktioniert, anstatt einige der anderen genannten Shell-basierten Lösungen auszuprobieren.
jdigital
1
Vor kurzem musste ein ähnliches Problem angehen. Am Ende habe ich mich für Perl entschieden (envsubst sah ein bisschen vielversprechend aus, aber es war zu schwer zu kontrollieren).
sfitts
5

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:

The number is ${i}
The word is ${word}

Die folgende Zeile bewirkt, dass die Shell den Inhalt von template.txt interpoliert und das Ergebnis in standard out schreibt.

i='1' word='dog' sh -c 'echo "'"$(cat template.txt)"'"'

Erläuterung:

  • iund wordwerden als Umgebungsvariablen übergeben, die zur Ausführung vonsh .
  • sh führt den Inhalt der übergebenen Zeichenfolge aus.
  • Nebeneinander geschriebene Zeichenfolgen werden zu einer Zeichenfolge. Diese Zeichenfolge lautet:
    • ' echo "' + " $(cat template.txt)" + '" '
  • Da liegt die Substitution zwischen " , wird " $(cat template.txt)" die Ausgabe von cat template.txt.
  • Also der Befehl ausgeführt von sh -c :
    • echo "The number is ${i}\nThe word is ${word}",
    • wo iund wordsind die angegebenen Umgebungsvariablen.
Apriori
quelle
Aus Sicherheitsgründen sind dies schlechte Nachrichten. Wenn Ihre Vorlage beispielsweise enthält, '$(rm -rf ~)'$(rm -rf ~)stimmen die wörtlichen Anführungszeichen in der Vorlagendatei mit denen überein, die Sie vor der Erweiterung hinzugefügt haben.
Charles Duffy
Ich glaube nicht, dass die Anführungszeichen in der Vorlage mit den Anführungszeichen in der Vorlage übereinstimmen. Ich glaube, dass die Shell die Vorlage und die In-Terminal-Zeichenfolge unabhängig voneinander auflöst (effektive Entfernung der Anführungszeichen) und sie dann verkettet. Eine Version des Tests, die Ihr Home-Verzeichnis nicht löscht, ist '$(echo a)'$(echo a). Es produziert 'a'a. Die Hauptsache, die passiert, ist, dass das erste im echo aInneren '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.
Apriori
Dies ist also nicht in dem Sinne sicher, dass der Vorlagenautor seinen Code ausführen kann. Die Bewertung der Anführungszeichen wirkt sich jedoch nicht wirklich auf die Sicherheit aus. Das Erweitern einer "Zeichenfolge mit Anführungszeichen (einschließlich $(...)) ist der Punkt.
Apriori
Ist das der Punkt? Ich sehe sie nur nach ${varname}weiteren Erweiterungen mit höherem Sicherheitsrisiko fragen .
Charles Duffy
... das heißt, ich muss mich unterscheiden (bezüglich: In-Template- und Out-Template-Anführungszeichen können übereinstimmen). Wenn Sie ein einfaches Anführungszeichen in Ihre Zeichenfolge echo "einfügen template.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 wird sh -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 Vorlage Gotcha"; rm -rf ~; echo "ausgeführt werden kann, die enthält .
Charles Duffy
4

file.tpl:

The following bash function should only replace ${var1} syntax and ignore 
other shell special chars such as `backticks` or $var2 or "double quotes". 
If I have missed anything - let me know.

script.sh:

template(){
    # usage: template file.tpl
    while read -r line ; do
            line=${line//\"/\\\"}
            line=${line//\`/\\\`}
            line=${line//\$/\\\$}
            line=${line//\\\${/\${}
            eval "echo \"$line\""; 
    done < ${1}
}

var1="*replaced*"
var2="*not replaced*"

template file.tpl > result.txt
user976433
quelle
2
Dies ist nicht sicher, da es Befehlsersetzungen in der Vorlage ausführt, wenn sie einen führenden Backslash haben, z. B.\$(date)
Peter Dolberg
1
Abgesehen von Peters gültigem Punkt: Ich schlage vor, Sie verwenden ihn while IFS= read -r line; doals readBefehl, andernfalls entfernen Sie führende und nachfolgende Leerzeichen aus jeder Eingabezeile. Außerdem echokönnte der Zeilenanfang mit einer der Befehlszeilenoptionen verwechselt werden, daher ist es besser, ihn zu verwenden printf '%s\n'. Schließlich ist es sicherer, doppelte Anführungszeichen zu setzen ${1}.
mklement0
4

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:

cat my-file.conf.template | sigil -p $(env) > my-file.conf

Dies ist viel sicherer als evalund einfacher als die Verwendung von Regex odersed

spudfkc
quelle
2
Gute Antwort! Es ist ein richtiges Template-System und viel einfacher zu bearbeiten als die anderen Antworten.
Erfan
Übrigens, besser zu vermeiden catund <my-file.conf.templatestattdessen zu verwenden, damit Sie sigilanstelle eines FIFO ein echtes Dateihandle geben.
Charles Duffy
2

Ich habe diesen Thread gefunden, als ich mich das Gleiche gefragt habe. Es hat mich dazu inspiriert (vorsichtig mit den Backticks)

$ echo $MYTEST
pass!
$ cat FILE
hello $MYTEST world
$ eval echo `cat FILE`
hello pass! world
GlueC
quelle
4
Eine Bash-Abkürzung für $(cat file)is$(< file)
Glenn Jackman
3
Anscheinend hat diese Methode die Zeilenumbrüche durcheinander gebracht, dh meine Datei wurde in einer Zeile wiedergegeben.
Arthur Corenzan
@ArthurCorenzan: In der Tat werden Zeilenumbrüche durch Leerzeichen ersetzt. Um dies zu beheben, müssten Sie verwenden, eval echo "\"$(cat FILE)\""aber das kann immer noch zu kurz kommen, da doppelte Anführungszeichen in der Eingabe verworfen werden.
mklement0
Wie an anderer Stelle erwähnt: Verwenden Sie diese Option nur, wenn Sie der Eingabe vollständig vertrauen oder sie steuern, da in die Eingabe eingebettete Befehlssubstitutionen ( `…` oder $(…)) die Ausführung beliebiger Befehle aufgrund der Verwendung von ermöglichen eval.
mklement0
2

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:

use Env;
Env::import();

while(<>) { $_ =~ s/(\${\w+})/$1/eeg; $text .= $_; }

print "$text";

Natürlich bin ich nicht wirklich eine Perl-Person, daher kann es leicht zu einem schwerwiegenden Fehler kommen (funktioniert aber für mich).

sfitts
quelle
1
Funktioniert gut. Sie könnten die Env::import();Zeile löschen - der Import wird durch impliziert use. Außerdem empfehle ich, nicht zuerst die gesamte Ausgabe im Speicher aufzubauen: Verwenden Sie einfach print;statt $text .= $_;innerhalb der Schleife und lassen Sie den Post-Loop- printBefehl fallen.
mklement0
1

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).

$ cat config.data
    export parm_jdbc=jdbc:db2://box7.co.uk:5000/INSTA
    export parm_user=pax
    export parm_pwd=never_you_mind

$ cat go.bash
    . config.data
    echo "JDBC string is " $parm_jdbc
    echo "Username is    " $parm_user
    echo "Password is    " $parm_pwd

$ bash go.bash
    JDBC string is  jdbc:db2://box7.co.uk:5000/INSTA
    Username is     pax
    Password is     never_you_mind

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).

$ cat config.data
    parm_jdbc=jdbc:db2://box7.co.uk:5000/INSTA # JDBC URL
    parm_user=pax                              # user name
    parm_pwd=never_you_mind                    # password

$ cat go.bash
    cat config.data
        | sed 's/#.*$//'
        | sed 's/[ \t]*$//'
        | sed 's/^[ \t]*//'
        | grep -v '^$'
        | sed 's/^/export '
        >config.data-compiled
    . config.data-compiled
    echo "JDBC string is " $parm_jdbc
    echo "Username is    " $parm_user
    echo "Password is    " $parm_pwd

$ bash go.bash
    JDBC string is  jdbc:db2://box7.co.uk:5000/INSTA
    Username is     pax
    Password is     never_you_mind

In Ihrem speziellen Fall könnten Sie Folgendes verwenden:

$ cat config.data
    export p_p1=val1
    export p_p2=val2
$ cat go.bash
    . ./config.data
    echo "select * from dbtable where p1 = '$p_p1' and p2 like '$p_p2%' order by p1"
$ bash go.bash
    select * from dbtable where p1 = 'val1' and p2 like 'val2%' order by p1

Dann leiten Sie die Ausgabe von go.bash an MySQL und voila weiter, hoffentlich zerstören Sie Ihre Datenbank nicht :-).

paxdiablo
quelle
1
Sie müssen die Variablen nicht aus der Datei config.data exportieren. es reicht aus, sie nur einzustellen. Sie scheinen die Vorlagendatei zu keinem Zeitpunkt zu lesen. Oder vielleicht ist die Vorlagendatei geändert und enthält die 'Echo'-Operationen ... oder fehlt mir etwas?
Jonathan Leffler
1
Guter Punkt bei den Exporten, ich mache das standardmäßig, damit sie für Unterschalen verfügbar sind und es keinen Schaden verursacht, da sie beim Verlassen sterben. Die 'Vorlagendatei' ist das Skript selbst mit seinen Echoanweisungen. Es ist nicht erforderlich, eine dritte Datei einzuführen - es handelt sich im Grunde genommen um eine Mailmerge-Operation.
Paxdiablo
1
Das "Skript selbst mit seinen Echoanweisungen" ist keine Vorlage, sondern ein Skript. Denken Sie an den Unterschied in Bezug auf Lesbarkeit (und Wartbarkeit) zwischen <xml type = "$ TYPE"> und echo '<xml type = "' $ TYPE '">'
Pierre-Olivier Vares
1
@Pierre, es gibt keine Echoanweisungen in meinem Konfigurationsskript, sie sind lediglich Exporte, und ich habe gezeigt, wie Sie selbst das mit einem minimalen Vorverarbeitungsaufwand vermeiden können. Wenn Sie über die Echo-Anweisung in meinen anderen Skripten (wie 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.
Paxdiablo
1
@paxdiablo: Anscheinend haben Sie gerade die Frage vergessen: << Ich möchte die Ausgabe einer "Template" -Datei in MySQL >> leiten. Die Verwendung einer Vorlage ist also die Frage, es ist nicht "das falsche Ende des Sticks". Das Exportieren von Variablen und das Echo in einem anderen Skript beantwortet die Frage überhaupt nicht
Pierre-Olivier Vares
0

Perl-Bearbeitung von potenziell mehreren Dateien mit Backups.

  perl -e 's/\$\{([^}]+)\}/defined $ENV{$1} ? $ENV{$1} : ""/eg' \
    -i.orig \
    -p config/test/*
Joehep
quelle