0

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.

Community
  • 1
  • 1
thebunnyrules
  • 1,520
  • 15
  • 22
  • 1
    Brains that are so frazzled shouldn't be programming. I'll remove the comment, but the issue is severe when you use `eval`. Since you've chosen to go with `eval` plus command substitution, protecting yourself from unexpected interpolations should be a top priority (and will be extremely tricky — I don't think I'd want to guarantee that I'd get it right). BEWARE! You were warned. Users can be vicious, sometimes by accident. – Jonathan Leffler Feb 16 '16 at 01:31
  • @JonathanLeffler Thanks for the warning. I'm making a buckup script in shell that I will eventually share with anyone who wants to use it. The variables they can input into prompt will simply allow them substitute 20 character long strings such as date/time stamp and the name of the PC/platform into 2-3 character long variables so they don't have to type it out everytime they run the script. Risk to systems are non-existent unless users decide to perform an attack on their own systems. – thebunnyrules Feb 19 '16 at 01:32
  • @JonathanLeffler You're not the first to warn me about using eval. For my own knowledge, what are the security risks associated with using it? The only thing I could think of is that a user can input harmful code into prompt but for that to do any damage they would need to run the script as sudo and if they can do that already, they can just run the code directly in bash. Are there any other threats it could pose that I didn't think about? – thebunnyrules Feb 19 '16 at 01:42
  • 1
    Read the descriptions and discussions at [What is the `eval` command in Bash](https://unix.stackexchange.com/questions/23111/), [Eval command and security issues](http://mywiki.wooledge.org/BashFAQ/048), [Why should `eval` be avoided in Bash, and what should I use instead](https://stackoverflow.com/questions/17529220/), [Unix shell injection attacks](http://homepage.cs.uiowa.edu/~jones/security/notes/12.shtml), and many others. – Jonathan Leffler Feb 19 '16 at 01:53

1 Answers1

1

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."

larsks
  • 277,717
  • 41
  • 399
  • 399
  • thanks so much for your help. I ended up using eval as proposed in the second part of your answer: newvariable="$(eval echo $input)". – thebunnyrules Feb 16 '16 at 01:19