You are right, eval is a security risk in this case. Here is one possible way:
pattern='The $a is $b when the $z is $x $c $g.' # simulated input from user (use "read") unset results for word in $pattern do case $word in \$a) results+=($(some_command)) # add output of some_command to array (output is "werewolf" ;; \$b) results+=($(echo "active")) ;; \$c) results+=($(echo "and")) ;; \$g) results+=($(echo "the sky is clear")) ;; \$x) results+=($(echo "full")) ;; \$z) results+=($(echo "moon")) ;; *) do_something # count the non-vars, do a no-op, twiddle thumbs # perhaps even sanitize %placeholders, terminal control characters, other unwanted stuff that the user might try to slip in ;; esac done pattern=${pattern//\$[abcgxz]/%s} # replace the vars with printf string placeholders printf "$pattern\n" "${results[@]}" # output the values of the vars using the pattern printf -v sentence "$pattern\n" "${results[@]}" # put it into a variable called "sentence" instead of actually printing it
The result will be βA werewolf is active when the moon is full and the sky is clear.β The program itself, if the pattern is equal to '$ x $ z outside $ c $ g, therefore $ a must be $ b.' then the output will be "The full moon will disappear and the sky will become clear, so the werewolf must be active."
Dennis Williamson May 25 '10 at 7:48 a.m. 2010-05-25 07:48
source share