1

Say I want to have a template somewhere which is multiline string:

I have some
text with ${placeholders}
in this and some ${different}
ones ${here} and ${there}

What would be my best way of replacing the placeholders with input from a user? Would here-documents be a good use?

2

Assuming [a] that no \<newline>, nor the characters \, $, or ` are used in the multiline string (or they are properly quoted), a here-document (and variables) is your best option:

#!/bin/sh

placeholders="value one"
different="value two"
here="value three"
there="value four"

cat <<-_EOT_
I have some
text with ${placeholders}
in this and some ${different}
ones ${here} and ${there}.
_EOT_

If executed:

$ sh ./script
I have some
text with value one
in this and some value two
ones value three and value four.

Of course, correctly playing with qouting, even one variable could do:

$ multilinevar='I have some
> text with '"${placeholders}"'
> in this and some '"${different}"'
> ones '"${here}"' and '"${there}"'.'
$ echo "$multilinevar"
I have some
text with value one
in this and some value two
ones value three and value four.

Both solutions could accept multiline variable placeholders.


[a]From the manual:

... the character sequence \<newline> is ignored, and \ must be used to quote the characters \, $, and `. ...

1

Here's a way to do this in bash. You need a recent version because I rely on associative arrays here

template=$(cat << 'END_TEMPLATE'
I have some
text with ${placeholders}
in this and some ${different}
ones ${here} and ${there}
END_TEMPLATE
)

mapfile -t placeholders < <(grep -Po '(?<=\$\{).+?(?=\})' <<< "$template" | sort -u)

declare -A data
for key in "${placeholders[@]}"; do
    read -p "Enter the '$key' value: " -r data[$key]
done

t=$template
while [[ $t =~ '${'([[:alnum:]_]+)'}' ]]; do
    t=${t//"${BASH_REMATCH[0]}"/"${data[${BASH_REMATCH[1]}]}"}
    #      ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    #      |                    + the value the user entered
    #      + the placeholder in the text
done

echo "$t"
0

Given user inputs one, two, three

The following command will replace all instances of a given ${placeholder} with your input:

sed -i 's/${placeholders}/one/g; s/${different}/two/g; s/${here}/three/g' yourTemplateFile

If you use this in a bash script and have the user input in shell variables this would do all the replacements in one command.

0

Tested with below script and worked fine

echo "enter count of userinput required"
read c
for ((i=1;i<=$c;i++))
do
echo "enter the values"
read input_$i
done

awk -v i="$input_1" -v j="$input_2" -v k="$input_3" -v l="$input_4"   '{gsub(/\${placeholders}/,i,$0);gsub(/\${different}/,j,$0);gsub(/\${here}/,k,$0);gsub(/\${there}/,l,$0);print $0}' filename >>filename_tmp && mv filename_tmp filename

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.