[sudhir.tataraju.WBLL0717E4418] ➤ cat test.sh
#!bin/bash
i=2
value2=abc
echo "`$value$i`"
Output:
[sudhir.tataraju.WBLL0717E4418] ➤ sh test.sh
test.sh: line 8: 2: command not found
Debug output:
[sudhir.tataraju.WBLL0717E4418] ➤ sh -x test.sh
+ i=2
+ value2=abc
++ 2
test.sh: line 8: 2: command not found
+ echo ''
How to get output abc without error?
To print a double quote, enclose it within single quotes or escape it with the backslash character. Display a line of text containing a single quote. To print a single quote, enclose it within double quotes or use the ANSI-C Quoting .
A double quote may be quoted within double quotes by preceding it with a backslash. If enabled, history expansion will be performed unless an ' ! ' appearing in double quotes is escaped using a backslash. The backslash preceding the ' !
You can't use double quotation within another double quotation to assign any string value. If you want to print double quote in the output then you have to use the backslash (\) with the string.
Single quotes won't interpolate anything, but double quotes will. For example: variables, backticks, certain \ escapes, etc. Enclosing characters in single quotes ( ' ) preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash.
What you are trying to do can be achieved much better with arrays.
values=( value1 value2 value3 "This is value 4" )
echo "${values[2]}"
values[2]="other_value"
echo "${values[2]}"
Variables can also be used as the index:
i=2
echo "${values[$i]}"
Arrays make looping over the values very easy:
#looping over values
for value in "${values[@]}"; do
echo "$value"
done
#looping over indexes
for index in "${!values[@]}"; do
echo "${values[$index]}"
done
If you don't consider sparse or associative arrays, you can also loop like this:
for (( index=0; index<${#values[@]}; index++ )); do
echo "${values[index]}"
done
Arrays are the right structure for your task. They offer great functionality. For more information on arrays, see: wiki.bash-hackers.org/syntax/arrays and Bash Reference Manual.
What you're asking for can be achieved in two ways (without antipatterns or eval
).
Use indirect expansion:
The basic form of parameter expansion is
${parameter}
. The value of parameter is substituted. [...] 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.
So what you want is:
#!/bin/bash
i=2
value2=abc
# Have a variable that expands to the name of the variable you want
myvar=value$i
# Use indirect expansion
echo "${!myvar}"
Realize that your design is very bad, and use some proper structure instead: Bash handles arrays. See PesaThe's answer. That's definitely the recommended method in your case.
Don't use eval
. Though it might look great, you need a good deal of practice of shell scripting before you understand all the problems with eval
. And when you have enough experience with Bash, you'll realize that you very very rarely need eval
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With