thebunnyrules
thebunnyrules

Reputation: 1670

Linux shell script: Allow user to use variables in input

I'm writing a shell-script for Linux terminal. I want to be able to input variables into a prompt. For example

test.sh:

test="Monkey in the middle..."
read -p "Enter input: " input
echo $input

output:

Enter input: $test
$test

I want to be able to input "$test" during the (read -p) prompt segment of the script and have the script echo "Monkey in the middle..." at the end instead of echoing "$test" as it does now.

How would I go about doing that?



UPDATE:

Using the answers provided to me here and in this thread (a big thanks to the contributors and commentators!), I managed to piece together this line which worked very well for me:

newvariable="$(eval echo $input)" 

Be, advised, I was warned more then once that using eval may pose a security risk. Keep that in mind if you opt for this solution.

Upvotes: 0

Views: 3851

Answers (1)

larsks
larsks

Reputation: 311387

There are a few different answers to this question.

If you are actually using bash, take a look at the bash(1) man page and read the Parameter Expansion section:

If the first character of parameter is an exclamation point (!), it introduces a level of variable indirection. Bash uses the value of the variable formed from the rest of parameter as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of parameter itself. This is known as indirect expansion. The exceptions to this are the expansions of ${!prefix*} and ${!name[@]} described below. The exclamation point must immediately follow the left brace in order to introduce indirection.

This means if you have:

read $input
echo "${!input}"

And the user enters "HOME", you will see the value of $HOME. For example, on my system:

Enter input: HOME
/home/lars

Alternatively, you can use the eval command, which should work fine in any Bourne-shell like environment:

eval [arg ...]

The args are read and concatenated together into a single command. This command is then read and executed by the shell, and its exit status is returned as the value of eval. If there are no args, or only null arguments, eval returns 0.

Your code might look like this:

read $input
eval echo "\$$input"

The shell will first expand the value of $input, so that the resulting command line -- assuming that someone enters HOME in response to the prompt -- is:

eval echo $HOME

The \$ is simply escaping the $ with the \ so that the shell does not interpret it as the beginning of a variable during the first pass through the command line.

But there's a problem here, consider:

Enter input: ;date
$
Sun Feb 14 21:13:33 EST 2016

In this example, the semicolon caused the shell to execute a command, which is not necessarily what we expected or desired. You can mitigate this somewhat with better quoting:

eval echo \""$input"\"

Which in the above example results in:

$ sh foo.sh 
Enter input: ;date
$;date

But the lesson here is "don't use eval in security sensitive situations."

Upvotes: 1

Related Questions