Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash expand variable in a variable

Tags:

bash

I'm trying to set up my PS1 prompt variable to dynamically choose a color. To do this, I've defined a bunch of local variables with color names:

$ echo $Green \033[0;32m 

but I was hoping to use those in dynamically assigning variables, but I can't figure out how to expand them properly:

> colorstr="\${$color}" > echo $colorstr ${Green} 

I've tried a dozen combinations of eval, echo, and double-quotes, and none seem to work. The logical way (I thought) to expand the variable results in an error:

> colorstr="${$color}" -bash: ${$color}: bad substitution 

(for clarity I've used > instead of $ for the prompt character, but I am using bash)

How can I expand that variable? i.e., somehow get the word "Green" to the value \033[0;32m? And prefereably, have bash or the terminal parse that \033[0;32m as the color green too.

EDIT: I was mis-using ${!x} and eval echo $x previously, so I've accepted those as solutions. For the (perhaps morbidly) curious, the functions and PS1 variable are on this gist: https://gist.github.com/4383597

like image 500
keflavich Avatar asked Dec 27 '12 03:12

keflavich


People also ask

How do you expand a variable in bash?

Parameter expansion comes in many forms in bash, the simplest is just a dollar sign followed by a name, eg $a. This form merely substitutes the value of the variable in place of the parameter expansion expression. The variable name can also optionally be surround by braces, eg ${a}.

How do you expand a variable in SED?

Just use double quotes instead of single quotes. You'll also need to use {} to delimit the number_line variable correctly and escape the \ , too.

What does ${} mean in bash?

$() means: "first evaluate this, and then evaluate the rest of the line". Ex : echo $(pwd)/myFile.txt. will be interpreted as echo /my/path/myFile.txt. On the other hand ${} expands a variable. Ex: MY_VAR=toto echo ${MY_VAR}/myFile.txt.


2 Answers

Using eval is the classic solution, but bash has a better (more easily controlled, less blunderbuss-like) solution:

  • ${!colour}

The Bash (4.1) reference manual says:

If the first character of parameter is an exclamation point (!), a level of variable indirection is introduced. 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.

For example:

$ Green=$'\033[32;m' $ echo "$Green" | odx 0x0000: 1B 5B 33 32 3B 6D 0A                              .[32;m. 0x0007: $ colour=Green $ echo $colour Green $ echo ${!colour} | odx 0x0000: 1B 5B 33 32 3B 6D 0A                              .[32;m. 0x0007: $ 

(The odx command is very non-standard but simply dumps its data in a hex format with printable characters shown on the right. Since the plain echo didn't show anything and I needed to see what was being echoed, I used an old friend I wrote about 24 years ago.)

like image 96
Jonathan Leffler Avatar answered Sep 23 '22 22:09

Jonathan Leffler


Using eval should do it:

green="\033[0;32m" colorstr="green" eval echo -e "\$$colorstr" test           # -e = enable backslash escapes test 

The last test is in color green.

like image 27
perreal Avatar answered Sep 24 '22 22:09

perreal