Remplir des espaces réservés dans un fichier en un seul passage
Question
J'ai un fichier texte squelette avec des chaînes de caractères génériques:
blah blah blah
blah $PLACEHOLDER_1$
blah
$PLACEHOLDER_2$
et ainsi de suite. Formulaire " spécifique " des espaces réservés n'a pas d'importance - je peux les changer pour ce qui est le plus confortable pour une mise en œuvre spécifique.
J'ai un script bash dans lequel je connais les valeurs pour les espaces réservés et je dois générer un nouveau fichier, les espaces réservés étant remplacés par des valeurs.
#! /bin/sh
PLACEHOLDER_1 = 'string 1'
PLACEHOLDER_2 = 'multiline
string
2'
# TODO: Generate file output.txt from file output.template
# using placeholders above.
Je peux le faire en plusieurs passes avec sed, mais ce n’est pas amusant. Je ne souhaite pas utiliser Perl. Je veux utiliser textutils et me baser uniquement.
Quel est le meilleur moyen de faire ce que je veux en un seul passage?
La solution
Vous pouvez toujours utiliser sed pour effectuer le remplacement en un seul passage. Il vous suffit de spécifier tous les remplacements en une seule commande.
par exemple.
sed -i 's/PLACEHOLDER_1/string 1/g;s/PLACEHOLDER_2/string 2/g' <file>
Autres conseils
Voici un moyen de le faire sans sed:
Tout d'abord, un fichier de modèle légèrement modifié dans lequel les espaces réservés sont des variables bash:
blah blah blah
blah $PLACEHOLDER_1
blah
$PLACEHOLDER_2
Et le script:
#! /bin/sh
templatefile=output.template
outputfile=output.txt
PLACEHOLDER_1='string 1'
PLACEHOLDER_2='multiline
string
2'
# DONE: Generate file output.txt from file output.template
# using placeholders above.
echo "$(eval "echo \"$(cat $templatefile)\"")" > $outputfile
Voici une version qui illustre un modèle contenu dans le script, mais avec une torsion. Il présente également les valeurs par défaut, qui peuvent également être utilisées dans la version du fichier de modèle, et vous pouvez également effectuer des opérations mathématiques dans le modèle:
#! /bin/sh
template='blah blah blah
blah $PLACEHOLDER_1
blah
${PLACEHOLDER_2:-"some text"} blah ${PLACEHOLDER_3:-"some
lines
of
text"} and the total is: $((${VAL_1:-0} + ${VAL_2:-0}))'
# default operands to zero (or 1) to prevent errors due to unset variables
outputfile=output.txt
# gears spin, bells ding, values for placeholders are computed
PLACEHOLDER_1='string 1'
PLACEHOLDER_2='multiline
string
2'
VAL_1=2
VAL_2=4
unset PLACEHOLDER_3 # so we can trigger one of the defaults
# Generate file output.txt from variable $template
# using placeholders above.
echo "$(eval "echo \"$template\"")" > $outputfile
Pas de sed, pas de boucles, juste des nids velus et des citations. Je suis sûr que toutes les citations vous protégeront contre les éléments malveillants contenus dans un fichier modèle, mais je ne vais pas vous le garantir.
En vous basant sur la réponse précédente, utilisez peut-être un tableau et calculez la chaîne sed?
#!/bin/sh
PLACEHOLDER[0]='string 1'
PLACEHOLDER[1]='multiline
string
2'
s="sed -i "
for(( i=0 ; i<${#PLACEHOLDER[*]} ; i++ )) ; do
echo ${PLACEHOLDER[$i]}
s=$s"s/PLACEHOLDER_$i/${PLACEHOLDER[$i]}/g;"
done
echo $s
Semble échouer sur les chaînes multilignes, cependant.
Je ne sais pas comment les tableaux Bash portables pourraient être. Extrait ci-dessus testé avec "GNU bash, version 3.2.17 (1) - release (i386-apple-darwin9.0)"
Ma seule solution bash:
TEMPLATE='
foo
$var1
bar
$var2'
eval "echo \"$TEMPLATE\""
Je suis tombé par hasard sur cette question parce que je cherchais exactement la même chose et que je trouvais envsubst (1)
.
Vous pouvez utiliser envsubst si cela ne vous dérange pas d'utiliser des variables d'environnement:
PLACEHOLDER_1='string 1' PLACEHOLDER_2='multiline
string
2' envsubst < output.template
Si vous avez beaucoup de variables, vous pouvez les stocker dans un fichier et simplement source
(rappelez-vous d'utiliser export
à la fin du fichier recherché!)