I need to have a very basic template system in shell to port a windows installer to linux. So I can not change the syntax of the template variables.
I want to take specific environment variables (starting with $ENV_PREFIX) and build a sed script of the form s/@@@${TEMPLATE_VARIABLE}@@@/$VALUE_OF_ENVIRONMENT_VARIABLE/
.
$TEMPLATE_VARIABLE is the name of the environment variable with the $ENV_PREFIX stripped off.
#!/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
Now I have all kinds of problems with this script:
env --null
, but could not combine this with the following grep. I thought I'd write a quick shell script for this but now I remember why I hate shell scripting... :-(
These Questions seem to answer part of my question:
The script is much simpler if you just write the sed
commands to a temporary file, rather than trying to put them in a single string (especially if any of the environment variables used for substitution contain spaces in their values).
#!/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
Don't screw around with IFS. changing IFS is going to render the REST of your script useless, because now instead of using a space you have to use \\012 to separate keywords;
Your problem is quite simple to solve and can be done using pure Bourne shell code:
#!/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
This script will create a sed script that should run against the template file as you see fit.
That's my current (working) solution:
#!/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}"
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.