2013-05-22 4 views
1

J'ai besoin d'un système de template très basique dans shell pour porter un programme d'installation Windows sur linux. Je ne peux donc pas changer la syntaxe des variables du modèle.Construire un script sed à partir de variables d'environnement spécifiques

Je veux prendre des variables d'environnement spécifiques (en commençant par $ ENV_PREFIX) et construire un script sed de la forme s/@@@${TEMPLATE_VARIABLE}@@@/$VALUE_OF_ENVIRONMENT_VARIABLE/. $ TEMPLATE_VARIABLE est le nom de la variable d'environnement avec le $ ENV_PREFIX effacé.

#!/usr/bin/env sh # no bashisms please! 

TEMPLATE_FILE=$1 
ENV_PREFIX="DMTMPL_" 

SED_SCRIPT="" 

OIFS="$IFS" 
IFS=$'\012' 
for VAR in "$(env | grep "^${ENV_PREFIX}")" 
do 
    VARIABLE=$(echo $VAR | cut -d= -f1 | cut -d_ -f2-) 
    SED_SCRIPT="${SED_SCRIPT}\ns/${VARIABLE}/${???}/g" 
done 

echo ${SED_SCRIPT} 
# invoke sed with $SED_SCRIPT on $TEMPLATE_FILE 

Maintenant, j'ai toutes sortes de problèmes avec ce script:

  • J'ai essayé de faire env --null, mais n'a pas pu combiner avec le grep suivant.
  • La boucle ne correspond pas exactement gérer une variable d'environnement dans chaque boucle
  • Je n'ai pas réussi à avoir SED_SCRIPT $ bien séparé avec les nouvelles lignes
  • Comment puis-je accéder à la valeur d'une variable lorsque le nom de la variable est stockée dans une autre variable? C'est ce que j'ai besoin de mettre où ??? sont dans le script.

Je pensais écrire un script shell rapide pour cela, mais maintenant je me souviens pourquoi je déteste les scripts shell ... :-(

Ces questions semblent répondre à une partie de ma question:

+0

Avant de répondre, pourquoi rechigne-vous sur "bashismes"? puisque vous les utilisez vous-même, par ex. $ (env | grep ...) est un bashisme –

+0

Le script ne doit pas dépendre de bash mais s'exécuter par exemple. sur le tiret qui pointe vers sur Debian. Je ne suis pas si facile à reconnaître tous les bashims moi-même. –

+0

tiret sera bien avec la solution que j'ai fournie ci-dessous, en fait cela devrait fonctionner sur le vieux shell korn et shell Bourne original aussi bien. jetez un oeil –

Répondre

0

1. problème majeur

Ne pas visser avec IFS. changer IFS va rendre le REST de votre script inutile, car maintenant, au lieu d'utiliser un espace, vous devez utiliser \ 012 pour séparer les mots-clés;

Votre problème est assez simple à résoudre et peut être fait en utilisant pur code shell Bourne:

#!/usr/bin/env sh # no bashisms please! 
TEMPLATE_FILE=$1 
ENV_PREFIX="DMTMPL_" 
delim='/' 
sedscript="myscript.$$.sed" 
rm -f $sedscript 
touch $sedscript 

VARS=$(env | grep "^${ENV_PREFIX}" | sed -e 's%^${ENV_PREFIX}%%') 
for v in ${VARS}; do 
    eval value='${'$v'}' 
    echo s${delim}@@@${v}@@@${delim}${value}${delim}g >> $sedscript 
done 
cat $sedscript 

# sed -f $sedscript $TEMPLATE_FILE 

Ce script crée un script sed qui devrait se présenter contre le fichier modèle comme bon vous semble.

1

Le script est beaucoup plus simple si vous écrivez simplement les commandes sed dans un fichier temporaire, plutôt que de les placer dans une seule chaîne (en particulier si l'une des variables d'environnement utilisées pour la substitution contient des espaces).

#!/usr/bin/env sh 

TEMPLATE_FILE=$1 
ENV_PREFIX="DMTMPL_" 

env | grep "^$ENV_PREFIX" | while IFS="=" read -r name value; do 
     printf "s/%s/%s/\n" "${name#$ENV_PREFIX}" "$value" 
     done > sed-script.txt 

cat sed-script.txt # Optional 
sed -f sed-script.txt "$TEMPLATE_FILE" 
rm sed-script.txt 
0

Voilà ma solution actuelle (travail):

#!/usr/bin/env sh 

set -e 

TEMPLATE=$1 

if [ -z "${TEMPLATE}" -o ! -f ${TEMPLATE} ] 
then 
    echo "Did not find template file: ${TEMPLATE}" 
    exit 1 
fi 

ENV_PREFIX="DMTMPL_" 

TEMPLATE_PREFIX="PLACEHOLDER_" 

SED_SCRIPT="" 

OIFS=$IFS 
# see https://bugs.launchpad.net/ubuntu/+source/dash/+bug/285651 
IFS=' 
' 

for VAR in `env | grep ^${ENV_PREFIX}` 
do 
    VARIABLE=$(echo $VAR | cut -d= -f1) 
    TEMPLATE_VARIABLE=$(echo $VARIABLE | cut -d_ -f2-) 
    VALUE=$(eval "echo \$$VARIABLE") 
    SED_SCRIPT="${SED_SCRIPT} --expression=\"s|${TEMPLATE_PREFIX}${TEMPLATE_VARIABLE}|${VALUE}|g\"" 
done 

eval "sed --in-place=.sed.orig --posix ${SED_SCRIPT} ${TEMPLATE}" 
+0

Il n'y a pas besoin d'eval, la solution de chepner est meilleure. – koola

Questions connexes