Je veux diriger la sortie d'un fichier "modèle" dans MySQL, le fichier ayant des variables comme ${dbName}
intercalées. Quel est l'utilitaire de ligne de commande pour remplacer ces instances et vider la sortie sur la sortie standard?
bash
command-line
text-processing
templating
Dana le Sane
la source
la source
cat
. Tout ce dont vous avez besoin estsed -e "s/\${i}/1/" -e "s/\${word}/dog/" template.text
.sed
attendra un texte échappé, ce qui est un problème.Mettre à jour
Voici une solution de yottatsa sur une question similaire qui ne remplace que des variables comme $ VAR ou $ {VAR}, et est un bref one-liner
Bien sûr, si je et le mot sont dans votre environnement, alors c'est juste
Sur mon Mac, il semble qu'il a été installé dans le cadre de gettext et de MacGPG2
Ancienne réponse
Voici une amélioration de la solution de mogsie sur une question similaire, ma solution ne vous oblige pas à escaler des guillemets doubles, c'est le cas de mogsie, mais la sienne est une ligne!
La puissance de ces deux solutions est que vous n'obtenez que quelques types d'extensions de shell qui ne se produisent pas normalement $ ((...)), `...` et $ (...), bien que la barre oblique inverse soit une caractère d'échappement ici, mais vous n'avez pas à vous soucier du fait que l'analyse a un bogue, et il fait très bien plusieurs lignes.
la source
envsubst
ne fonctionne pas si vos envars ne sont pas exportés.envsubst
, comme son nom l'indique, ne reconnaît que les variables d' environnement , pas les variables shell . Il convient également de noter qu'ilenvsubst
s'agit d'un utilitaire GNU , et donc non préinstallé ou disponible sur toutes les plates-formes.Utilisez
/bin/sh
. Créez un petit script shell qui définit les variables, puis analysez le modèle à l'aide du shell lui-même. Comme ça (modifier pour gérer correctement les nouvelles lignes):Fichier template.txt:
Fichier script.sh:
Production:
la source
bash
commandes de l'entrée seront exécutées. Si le modèle est: "les mots sont; rm -rf $ HOME" vous perdrez des fichiers.read
commande, telle qu'elle est écrite, supprime les espaces de début et de fin de chaque ligne et `` mange '' les\
caractères., (C) ne l'utilise que si vous faites confiance ou contrôlez l'entrée, car les substitutions de commandes (`…`
ou$(…)
) intégrées dans l'entrée permettent l'exécution de commandes arbitraires en raison de l'utilisation deeval
. Enfin, il y a une petite chance queecho
le début d'une ligne soit confondu avec l'une de ses options de ligne de commande.J'y réfléchissais à nouveau, compte tenu de l'intérêt récent, et je pense que l'outil auquel je pensais à l'origine était
m4
le processeur de macros pour les outils automatiques. Donc, au lieu de la variable que j'ai spécifiée à l'origine, vous utiliseriez:la source
envsubst
pour cette simple utilisation de remplacement de variable / modèle, comme mentionné dans d'autres réponses.m4
est un excellent outil, mais c'est un préprocesseur complet avec beaucoup plus de fonctionnalités et donc une complexité qui peut ne pas être nécessaire si vous souhaitez simplement remplacer certaines variables.template.txt
data.sh
parser.sh
parsed_file.txt
la source
`…`
ou$(…)
) intégrées dans l'entrée permettent l'exécution de commandes arbitraires en raison de l'utilisation deeval
, et l'exécution directe du code shell en raison de l'utilisation desource
. De plus, les guillemets doubles dans l'entrée sont discrètement ignorés etecho
peuvent confondre le début d'une ligne avec l'une de ses options de ligne de commande.Voici une fonction Bash robuste qui, malgré l'utilisation
eval
, devrait être sûre à utiliser.Tout
${varName}
les références de variable dans le texte d'entrée sont développées en fonction des variables du shell appelant.Rien d'autre n'est développé: ni les références de variables dont les noms ne sont pas inclus dans
{...}
(comme$varName
), ni les substitutions de commandes ($(...)
et la syntaxe héritée`...`
), ni les substitutions arithmétiques ($((...))
et la syntaxe héritée$[...]
).Pour traiter a
$
comme un littéral,\
-escape it; par exemple:\${HOME}
Notez que l'entrée n'est acceptée que via stdin .
Exemple:
Code source de la fonction:
La fonction suppose qu'aucun
0x1
,0x2
,0x3
, et les0x4
caractères de contrôle sont présents dans l'entrée, parce que ces caractères. sont utilisés en interne - puisque la fonction traite du texte , cela devrait être une hypothèse sûre.la source
eval
il est assez sûr à utiliser."
correctement!)${FOO:-bar}
ou de ne sortir quelque chose que si elle est définie -${HOME+Home is ${HOME}}
. Je soupçonne qu'avec une petite extension, il pourrait également renvoyer des codes de sortie pour les variables manquantes,${FOO?Foo is missing}
mais tldp.org/LDP/abs/html/parameter-substitution.html n'a pas actuellement une liste de ceux-ci si cela aideCréer
rendertemplate.sh
:Et
template.tmpl
:Rendre le modèle:
la source
$(rm -rf ~)
, vous l'exécutez sous forme de code.eval "echo \"$(cat $1)\""
Fonctionne très bien !voici ma solution avec perl basée sur l'ancienne réponse, remplace les variables d'environnement:
la source
Si vous êtes prêt à utiliser Perl , ce serait ma suggestion. Bien qu'il existe probablement des experts sed et / ou AWK qui savent probablement comment faire cela beaucoup plus facilement. Si vous avez un mappage plus complexe avec plus que dbName pour vos remplacements, vous pouvez l'étendre assez facilement, mais vous pouvez tout aussi bien le mettre dans un script Perl standard à ce stade.
Un court script Perl pour faire quelque chose d'un peu plus compliqué (gérer plusieurs clés):
Si vous nommez le script ci-dessus comme replace-script, il pourrait alors être utilisé comme suit:
la source
Voici un moyen pour que le shell fasse la substitution à votre place, comme si le contenu du fichier était à la place tapé entre guillemets.
En utilisant l'exemple de template.txt avec le contenu:
La ligne suivante amènera le shell à interpoler le contenu de template.txt et à écrire le résultat dans la sortie standard.
Explication:
i
etword
sont transmises en tant que variables d'environnement limitées à l'exécution desh
.sh
exécute le contenu de la chaîne qui lui est transmise.echo "
' + "$(cat template.txt)
" + '"
'"
, "$(cat template.txt)
" devient la sortie decat template.txt
.sh -c
devient:echo "The number is ${i}\nThe word is ${word}"
,i
etword
sont les variables d'environnement spécifiées.la source
'$(rm -rf ~)'$(rm -rf ~)
les guillemets littéraux dans le fichier de modèle correspondent à ceux que vous avez ajoutés avant son expansion.'$(echo a)'$(echo a)
. Cela produit'a'a
. La principale chose qui se passe est que le premierecho a
à l'intérieur de'
est évalué, ce qui n'est peut-être pas ce à quoi vous vous attendez puisqu'il est dans'
, mais c'est le même comportement que l'inclusion'
dans une"
chaîne entre guillemets."
chaîne entre guillemets (y compris$(...)
) est le point.${varname}
, pas d'autres extensions à haut risque de sécurité.echo "
, suivie d'une chaîne entre guillemets doubles avec les contetns littéraux detemplate.txt
, suivie d'une autre chaîne littérale"
, le tout concaténé en un seul argument passé àsh -c
. Vous avez raison de dire que le'
ne peut pas être mis en correspondance (car il a été consommé par le shell externe plutôt que passé à l'intérieur), mais le"
peut certainement, donc un modèle contenantGotcha"; rm -rf ~; echo "
pourrait être exécuté.file.tpl:
script.sh:
la source
\$(date)
while IFS= read -r line; do
commeread
commande, sinon vous supprimerez les espaces blancs de début et de fin de chaque ligne d'entrée. De plus,echo
pourrait confondre le début d'une ligne avec l'une de ses options de ligne de commande, il est donc préférable d'utiliserprintf '%s\n'
. Enfin, il est plus sûr de double-citer${1}
.Je suggérerais d'utiliser quelque chose comme Sigil : https://github.com/gliderlabs/sigil
Il est compilé en un seul binaire, il est donc extrêmement facile à installer sur les systèmes.
Ensuite, vous pouvez faire un simple one-liner comme suit:
C'est beaucoup plus sûr
eval
et plus facile que d'utiliser regex oused
la source
cat
et utiliser à la<my-file.conf.template
place afin de donnersigil
un vrai handle de fichier au lieu d'un FIFO.J'ai trouvé ce fil en me demandant la même chose. Cela m'a inspiré (attention aux backticks)
la source
$(cat file)
is$(< file)
eval echo "\"$(cat FILE)\""
mais cela peut toujours être insuffisant dans la mesure où les guillemets doubles dans l'entrée sont ignorés.`…`
ou$(…)
) intégrées dans l'entrée permettent l'exécution de commandes arbitraires en raison de l'utilisation deeval
.Beaucoup de choix ici, mais je pensais que je mettrais le mien sur le tas. Il est basé sur Perl, ne cible que les variables de la forme $ {...}, prend le fichier à traiter comme argument et renvoie le fichier converti sur stdout:
Bien sûr, je ne suis pas vraiment une personne perl, donc il pourrait facilement y avoir un défaut fatal (cela fonctionne pour moi cependant).
la source
Env::import();
ligne - l'importation est implicite paruse
. De plus, je suggère de ne pas commencer par créer la totalité de la sortie en mémoire: utilisez simplementprint;
au lieu de l'$text .= $_;
intérieur de la boucle et supprimez laprint
commande post-boucle .Cela peut être fait dans bash lui-même si vous avez le contrôle du format du fichier de configuration. Vous avez juste besoin de source (".") Le fichier de configuration plutôt que de le sous-shell. Cela garantit que les variables sont créées dans le contexte du shell actuel (et continuent d'exister) plutôt que du sous-shell (où la variable disparaît lorsque le sous-shell se termine).
Si votre fichier de configuration ne peut pas être un script shell, vous pouvez simplement le «compiler» avant de l'exécuter ainsi (la compilation dépend de votre format d'entrée).
Dans votre cas spécifique, vous pouvez utiliser quelque chose comme:
Puis dirigez la sortie de go.bash dans MySQL et voilà, j'espère que vous ne détruirez pas votre base de données :-).
la source
go.bash
), vous avez le mauvais bout du bâton - ils ne font pas partie de la solution, ils sont juste un moyen de montrer que les variables sont réglé correctement.Mise en place de l'édition perl de fichiers potentiellement multiples, avec des sauvegardes.
la source
Vous voudrez quelque chose de plus robuste que les suggestions actuelles car bien qu'elles fonctionnent pour votre cas d'utilisation limité (pour l'instant), elles ne suffiront pas pour des situations plus complexes.
Vous avez besoin d'un meilleur moteur de rendu. Vous avez besoin du meilleur moteur de rendu. Vous avez besoin de The Renderest!
Template.txt donné:
Salut toi}}!
Courir:
$ person = Bob ./render template.txt
Et vous verrez la sortie
Bonjour bob!
Écrivez-le dans un fichier en redirigeant stdout vers un fichier:
$ person = Bob ./render template.txt> rendu.txt
Et si vous effectuez le rendu d'un script contenant des variables $ {} que vous ne voulez pas interpoler, The Renderest vous couvre sans que vous ayez à faire autre chose!
Continuez et obtenez votre copie sur https://github.com/relaxdiego/renderest
la source