0

I'm looking for a Bash equivalent for the following python code:

template = 'The {part} on the {vehicle} goes {action} and {action}.'

template.format(part='wheels', vehicle='bus', action='round')
## or ##
vals = {'part': 'wheels', 'vehicle': 'bus', 'action': 'round'}
template.format(**vals)

desired result:

'The wheels on the bus go round and round.'

Does bash have a feature like this? If not, is there a way to simulate this behaviour?


I know I can format strings with printf like this:

template="The %s on the %s go %s and %s."
part="wheels"
vehicle="bus"
action="round"

printf "${template}" ${part} ${vehicle} ${action} ${action}
## or ##
vals=(${part} ${vehicle} ${action} ${action})
printf "${template}" ${vals[@]}

...but I don't want to have to provide the same value more than once if it appears in the string multiple times, like "action" does.

I wish I could do something like this:

declare -A vals=(["part"]="wheels" ["vehicle"]="bus" ["action"]="round")
printf "${template}" ${vals[@]}

I am also aware of string replacement like this:

string="${string//old/new}"

which I thought I could put into a function which iterates over an associative array and replaces the keys with values, but I couldn't get this to work mainly because passing associative arrays as arguments is non-trivial. I'm sure I could eventually find a workaround, but the workaround needs to be less onerous than simply putting up with printf's shortcomings.

3
  • Related, see the TemplateFiles page on the Wooledge wiki. Commented Apr 15, 2020 at 23:21
  • 1
    @CharlesDuffy I agree with the wiki, but are there no better duplicates without eval? Commented Apr 15, 2020 at 23:33
  • That dupe target sucks, there is a much more straightforward and understandable answer right here. Commented Nov 14 at 15:48

1 Answer 1

1

Using envsubst, you could do:

template='The ${part} on the ${vehicle} goes ${action} and ${action}.'
part="wheels" vehicle="bus" action="round" envsubst <<<"$template"

or

template='The ${part} on the ${vehicle} goes ${action} and ${action}.'

export part="wheels"
export vehicle="bus"
export action="round"

envsubst '$part $vehicle $action' <<<"$template"

Or for a longer text, use a here-document:

part="wheels"
vehicle="bus"
action="round"

cat <<EOF
The ${part}
  on the ${vehicle}
goes ${action}
  and ${action}.
EOF
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.