Frage

Ich möchte die Ausgabe einer "Vorlage" -Datei in MySQL übergeben, die Datei mit Variablen wie ${dbName} durchsetzt. Was ist das Dienstprogramm für Befehlszeilen, um diese Instanzen zu ersetzen und die Ausgabe in die Standardausgabe abzugeben?

War es hilfreich?

Lösung

Sed!

Gegebene Vorlage.txt:

The number is ${i}
The word is ${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, um mehrere zu bestehen -e Argumente an das gleiche sed Aufruf.

Andere Tipps

Aktualisieren

Hier ist eine Lösung von Yottatsa Auf eine ähnliche Frage, die nur Ersatz für Variablen wie $ var oder $ {var} ersetzt und ein kurzer Ein-Liner ist

i=32 word=foo envsubst < template.txt

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

envsubst < template.txt

Auf meinem Mac sieht es so aus, als wäre es als Teil von installiert worden GetText und von MACGPG2

Alte Antwort

Hier ist eine Verbesserung der Lösung von Mogsie Bei einer ähnlichen Frage müssen Sie nicht die Doppelzitate von Mogsie begleiten, aber sein ist ein Ein -Liner!

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

Die Macht dieser beiden Lösungen besteht ist Ein Fluchtcharakter hier, aber Sie müssen sich keine Sorgen machen, dass das Parsen einen Fehler hat und es mehrere Zeilen gut macht.

Verwenden /bin/sh. Erstellen Sie ein kleines Shell -Skript, das die Variablen festlegt, und analysieren Sie die Vorlage mit der Shell selbst. Lust auf (bearbeiten, um Neulinien korrekt zu handhaben):

Dateivorlage.txt:

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

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

Ich habe angesichts des jüngsten Interesses noch einmal darüber nachgedacht und ich denke, dass das Werkzeug, an das ich ursprünglich gedacht habe, war m4, der Makroprozessor für Autotools. Anstelle der Variablen, die ich ursprünglich angegeben habe, würden Sie verwenden:

$echo 'I am a DBNAME' | m4 -DDBNAME="database name"

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 Vorlage.txt parsed_file.txt

parsed_file.txt

Variable 1 value: value 1
Variable 2 value: value 2

Hier ist meine Lösung mit Perl basierend auf früherer Antwort ersetzt Umgebungsvariablen:

perl -p -e 's/\$\{(\w+)\}/(exists $ENV{$1}?$ENV{$1}:"missing variable $1")/eg' < infile > outfile

Hier ist ein robuste Bash -Funktion das - trotzdem verwendet eval - sollte sicher zu bedienen sein.

Alle ${varName} Variable Referenzen im Eingabetext werden basierend auf den Variablen der aufrufenden Shell erweitert.

Nichts anderes wird erweitert: Weder variable Referenzen, deren Namen sind nicht Eingeschlossen in {...} (wie zum Beispiel $varName), noch Befehlssubstitutionen ($(...) und Legacy -Syntax `...`), noch arithmetische Substitutionen ($((...)) und Legacy -Syntax $[...]).

A $ als wörtlich, \-Schape es; z.B:\${HOME}

Beachten Sie, dass die Eingabe nur durch akzeptiert wird Stdin.

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 geht davon aus 0x1, 0x2, 0x3, und 0x4 Steuerzeichen sind in der Eingabe vorhanden, da diese Zeichen. werden intern verwendet - seit den Funktionsprozessen Text, das sollte eine sichere Annahme sein.

Wenn Sie offen für die Verwendung sind Perl, das wäre mein Vorschlag. Obwohl es wahrscheinlich einige gibt sed und/oder Awk Experten, die wahrscheinlich wissen, wie man das viel einfacher macht. Wenn Sie eine komplexere Zuordnung mit mehr als nur DBNAME für Ihren Ersatz haben, können Sie dies ziemlich leicht erweitern, aber Sie könnten es 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 zu handeln):

#!/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 Ersatzkript nennen, kann es wie folgt verwendet werden:

replace-script < yourfile | mysql

Schaffen rendertemplate.sh:

#!/usr/bin/env bash

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

Und template.tmpl:

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

Die Vorlage rendern:

$ export WORLD=Foo
$ CHEESE=Bar ./rendertemplate.sh template.tmpl 
Hello, Foo
Goodbye, Bar

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

Ich würde vorschlagen, so etwas zu verwenden Sigil: https://github.com/gliderlabs/sigil

Es ist mit einer einzigen Binärdatei zusammengestellt, sodass es extrem einfach auf Systemen installiert ist.

Dann können Sie einen einfachen Einzeiler wie folgt machen:

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

Das ist viel sicherer als eval und einfacher als Regex oder sed

Ich habe diesen Thread gefunden, während ich mich dasselbe 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

Viele Auswahlmöglichkeiten hier, aber ich dachte, ich würde meinen auf den Haufen werfen. Es basiert Perl, zielt nur an Variablen des Formulars $ {...}, nimmt die Datei als Argument zur Verarbeitung 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, also könnte es leicht einen fatalen Fehler geben (aber für mich funktioniert).

Dies kann in Bash selbst erfolgen, wenn Sie die Kontrolle über das Konfigurationsdateiformat haben. Sie müssen nur die Konfigurationsdatei beziehen ("."), Anstatt sie zu unterschalen. Dies stellt sicher, dass die Variablen im Kontext der aktuellen Schale erstellt werden (und existieren weiterhin) und nicht im Unterschalen (wo die Variable verschwindet, wenn die Unterschale beendet ist).

$ 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 einfach vor der Ausführung "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 so etwas verwenden wie:

$ 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 machen Sie die Ausgabe von Go.Bash in MySQL und Voila, hoffentlich werden Sie Ihre Datenbank nicht zerstören :-).

Hier ist eine Möglichkeit, die Shell dazu zu bringen, den Substitution für Sie durchzuführen, als ob der Inhalt der Datei stattdessen zwischen Doppelzitaten tippt würde.

Verwenden des Beispiels von template.txt mit Inhalten:

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

Die folgende Zeile veranlasst die Shell, den Inhalt von Template zu interpolieren.

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

Erläuterung:

  • i und word werden als Umgebungsvariablen übergeben, sh.
  • sh führt den Inhalt der Zeichenfolge aus, die sie übergeben wird.
  • Saiten, die nebeneinander geschrieben wurden, werden zu einer Zeichenfolge, diese Zeichenfolge lautet:
    • 'echo "' + "$(cat template.txt)" + '"'
  • Da ist die Substitution dazwischen ", "$(cat template.txt)"wird zur Ausgabe von cat template.txt.
  • Also der Befehl von ausgeführt von sh -c wird:
    • echo "The number is ${i}\nThe word is ${word}",
    • wo i und word sind die angegebenen Umgebungsvariablen.
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top