Using a variable to refer to another variable in Bash - bash

x=1
c1=string1
c2=string2
c3=string3
echo $c1
string1
I'd like to have the output be string1 by using something like:
echo $(c($x))
So later in the script I can increment the value of x and have it output string1, then string2 and string3.
Can anyone point me in the right direction?

See the Bash FAQ: How can I use variable variables (indirect variables, pointers, references) or associative arrays?
To quote their example:
realvariable=contents
ref=realvariable
echo "${!ref}" # prints the contents of the real variable
To show how this is useful for your example:
get_c() { local tmp; tmp="c$x"; printf %s "${!tmp}"; }
x=1
c1=string1
c2=string2
c3=string3
echo "$(get_c)"
If, of course, you want to do it the Right Way and just use an array:
c=( "string1" "string2" "string3" )
x=1
echo "${c[$x]}"
Note that these arrays are zero-indexed, so with x=1 it prints string2; if you want string1, you'll need x=0.

Try this:
eval echo \$c$x
Like others said, it makes more sense to use array in this case.

if you have bash 4.0, you can use associative arrays.. Or you can just use arrays. Another tool you can use is awk
eg
awk 'BEGIN{
c[1]="string1"
c[2]="string2"
c[3]="string3"
for(x=1;x<=3;x++){
print c[x]
}
}'

Related

Creating and populating dynamically named arrays in bash

I am creating dynamic arrays which all have different letters in their name. For the purpose of this question, my initial array of letters has been set at a fixed length. However, in my final implementation this letter array will be any length.
For each letter, I construct a string
I declare a new array with that string, making use of eval to evaluate the variable's value within the declare command.
I add some values to the array, again using eval to evaluate any variable values.
Here is the code:
declare -a LETTER_ARRAY=( "A" "B" "C" "D" "E" )
for i in "${LETTER_ARRAY[#]}"
do
name_string="apple${i}"
color0="red"
color1="green"
eval "declare -a ${name_string}_array"
eval "${name_string}_array[0]=$color0"
eval "${name_string}_array[1]=$color1"
done
So, how can I iterate through these dynamic arrays and echo what is in them? I have tried the following:
for i in "${LETTER_ARRAY[#]}"
do
eval "array_name='apple${i}_array'"
echo ${array_name[0]}
done
This has not worked for me. I can confirm that my dynamic arrays were successfully created and populated, as when I echo out a value manually, I get a result:
echo ${appleA_array[0]}
red
A perfect place to use a namereference:
letter_array=(A B C D E)
for i in "${letter_array[#]}"; do
declare -n var="apple${i}_array"
var[0]=red
var[1]=green
done
declare -p appleA_array
would output:
declare -a appleA_array=([0]="red" [1]="green")
how can I iterate through these dynamic arrays and echo what is in them?
With the above:
for i in "${letter_array[#]}"; do
declare -n var="apple${i}_array"
printf "%s\n" "${var[0]}"
done
Notes:
Do not use eval. Eval is evil.
Do not use upper case variables, by convention they are used for exported variables, like COLUMNS, PWD, UID, EUID, LINES. Use lower case variables in your scripts.
Check your scripts with http://shellcheck.net for most common mistakes
But if you are creating a 2d array, then an associative array might be better:
declare -A apple_arrays
letter_array=(A B C D E)
for i in "${letter_array[#]}"; do
apple_arrays[$i,0]=red
apple_arrays[$i,1]=green
done
for i in "${letter_array[#]}"; do
printf "one=%s two=%s\n" "${apple_arrays[$i,0]}" "${apple_arrays[$i,1]}"
done
how can I iterate through these dynamic arrays
echo ${array_name[0]} does not work because array_name is not the name of an array; $array_name is. Therefore, eval "echo \"\${${array_name}[0]}\"" would to the trick.
However, I'd recommend namerefs.
By The way: declare works without eval and is more reliable that way.
#! /usr/bin/env bash
letters=({A..E})
for i in "${letters[#]}"; do
declare -a "apple${i}_array=(red green)"
done
for i in "${letters[#]}"; do
declare -n array="apple${i}_array"
# now you can use `array` as if it was `appleA_array`, `appleB_array`, ...
echo "${array[0]}"
done
Your first line is not bash syntax. If I try the line
declare -a LETTER_ARRAY = [ "A" "B" "C" "D" "E" ]
I get:
bash: declare: `=': not a valid identifier
bash: declare: `[': not a valid identifier
bash: declare: `]': not a valid identifier
I think, you get similar error messages, but you ignored them
More errors:
Forgotten do
case mismatch: suffix on definition: _array, and for output: _ARRAY
Use always double quotes when using [#]
One correct syntax is:
declare -a LETTER_ARRAY=( "A" "B" "C" "D" "E" )
for i in "${LETTER_ARRAY[#]}"
do
name_string="apple${i}"
color0="red"
color1="green"
eval "declare -a ${name_string}_array"
echo "${name_string}_array[0]=$color0"
eval "${name_string}_array[0]=$color0"
eval "${name_string}_array[1]=$color1"
done
echo ${appleA_array[0]}
Your eval "array_name='AZ${i}_ARRAY'" makes array_name a scalar, not an array. Arrays in bash are usually created like this
arr=( your elements go here )
If you want to assign one array to another, you have to interpolate the elements between those parenthesis, for instance:
arr=( ${other_array[#]} )
Since you are using bash, this would perform word splitting the elements of other_array, if they contain spaces. Hence you would usually write it for the safe side as
arr=( "${other_array[#]}" )
Hence, for your case, you could do a
eval "array_name=( \${AZ${i}_ARRAY[#]} )"
This causes an array array_name to be created, with the elements of the respective AZi_ARRAY.
I omitted here for simplicity the prevention against word splitting, because in your example, the array elements contain single words only.

Bash variable within varaible [duplicate]

x=1
c1=string1
c2=string2
c3=string3
echo $c1
string1
I'd like to have the output be string1 by using something like:
echo $(c($x))
So later in the script I can increment the value of x and have it output string1, then string2 and string3.
Can anyone point me in the right direction?
See the Bash FAQ: How can I use variable variables (indirect variables, pointers, references) or associative arrays?
To quote their example:
realvariable=contents
ref=realvariable
echo "${!ref}" # prints the contents of the real variable
To show how this is useful for your example:
get_c() { local tmp; tmp="c$x"; printf %s "${!tmp}"; }
x=1
c1=string1
c2=string2
c3=string3
echo "$(get_c)"
If, of course, you want to do it the Right Way and just use an array:
c=( "string1" "string2" "string3" )
x=1
echo "${c[$x]}"
Note that these arrays are zero-indexed, so with x=1 it prints string2; if you want string1, you'll need x=0.
Try this:
eval echo \$c$x
Like others said, it makes more sense to use array in this case.
if you have bash 4.0, you can use associative arrays.. Or you can just use arrays. Another tool you can use is awk
eg
awk 'BEGIN{
c[1]="string1"
c[2]="string2"
c[3]="string3"
for(x=1;x<=3;x++){
print c[x]
}
}'

making variable with the values of another variable in unix shell scripting

I need to make variable using two other variable values.
#i have two variable in unix i.e.#
v_a=a
v_b=b
##now i want to combine the two values of the two variable and the result of that i want that as a variable means v_a_b and use it.##
echo 'v_'$v_a'_'$v_b #the output will be v_a_b and i want to use it like $v_a_b
Suppose you have the following vars:
v_a=a
v_b=b
v_a_b="I want this one"
v_a_c="Wrong one!"
How do you get I want this one using the values of v_a and v_b ?
You can use eval, but try to avoid that:
# don't do this
eval echo "\$v_${v_a}_${v_b}"
You need a new variable , lets call it c and get the value of the constructed var:
c="v_${v_a}_${v_b}"
echo "Using the exclamation mark for retrieving the valueCombined: ${!c}"
Another way is using printf:
printf -v c "v_%s_%s" "${v_a}" "${v_b}"
echo "Combined: ${!c}"
Use eval to explicitly pre-evaluate an expression.
for your question,
eval 'echo \$v_"$v_a"_"$v_b"'
should work fine,
echo \$v_"$v_a"_"$v_b" evaluates to echo $v_a_b, then the intermediate result is evaluated again, so in effect, we get the result of $(echo $v_a_b)
note: you might want to quote the variable $v_a_b:
eval 'echo \"\$v_"$v_a"_"$v_b"\"'
If I understand correctly, you want to concatenate the contents of variables v_a and v_b (along with some fixed strings 'v_' and '_') then store it in a variable named v_a_b.
v_a=a
v_b=b
v_a_b='v_'$a'_'$b
echo $v_a_b
The output is v_a_b.
v_a=a
v_b=b
v_a_b=c
eval V_XYZ='$'"v_"$v_a"_"$v_b
echo 'Value= '$V_XYZ
output will be c

Echo $variable$counter in a "for" loop BASH

n=1
test=1000
test1=aaa
I'm trying:
echo $test$n
to get
aaa
But I get
10001
I'm trying to use it that way because I have variables: lignePortTCP1,lignePortTCP2,lignePortTCP1, ETC in a for loop like this:
declare -i cpt3
cpt3=0
for ((i = 1; i <= cpt; i++)); do
cpt3=cpt3+1
echo "Port/Protocole : $lignePortTCP$cpt3 - Nom du Service : $ligneServiceTCP$cpt3"
done
Given the assigned variables
n=1
test1=aaa
...and you want to print aaa given the values of test and n, then put the name you want to expand in its own variable, and expand that with the ! operator, like so:
varname="test$n"
echo "${!varname}"
This is explicitly discussed in BashFAQ #6.
That said, variable indirection is not a particularly good practice -- usually, you can do better using arrays, whether associative or otherwise.
For instance:
test=( aaa bbb ccc )
n=0
echo "${test[n]}"
...for values not starting at 0:
test=( [1]=aaa [2]=bbb [3]=ccc )
n=1
echo "${test[n]}"
If you want to subtract the values of test and n, wrap the computation in $(( ... )) and use
the - operator:
$((test-n))
You could also use eval, though it's probably not better than the technique provided by Charles Duffy.
$ n=1
$ test=1000
$ test1=aaa
$ eval echo \${test$n}
aaa
One way would be to use ${!}, but you have to store the combined name in its own variable for that to work:
var=test$n
echo "${!var}"
If you have control over how the variables get assigned in the first place, it would be better to use an array. Instead of lignePortTCP1, lignePortTCP2, etc., you would assign the values to lignePortTCP[0], lignePortTCP[1], etc. and then retrieve them with ${lignePort[$n]}.

how to use array as function variable in bash

I want to pass an array parameter to a function in bash, and writing some testing code as:
#!/bin/sh
function foo {
a=$1;
for i in ${a[#]} ; do
echo $i
done
}
names=(jim jerry jeff)
foo ${names[#]}
the above code just show jim, rather than the three j*. so my question is:
why my code doesn't work
what's the right way to do it
#!/bin/bash
function foo {
a=($*)
for i in ${a[#]}
do
echo $i
done
}
names=(jim jerry jeff)
foo ${names[#]}
Your code did not show jim to me, but "names", literally. You have to pass the whole array. And you have to recapture it with a=$($).
The manpage part in bash about Arrays is rather long. I only cite one sentence:
Referencing an array variable without a subscript is equivalent to referencing the array with a subscript of 0.
You're fairly close; the biggest problem was the command a=$1, which assigns only the first parameter ($1) to a, while you want to assign the entire list of parameters ($#), and assign it as an array rather than as a string. Other things I corrected: you should use double-quotes around variables whenever you use them to avoid confusion with special characters (e.g. spaces); and start the script with #!/bin/bash, since arrays are a bash extension, not always available in a brand-X shell.
#!/bin/bash
function foo {
a=("$#")
for i in "${a[#]}" ; do
echo "$i"
done
}
names=(jim jerry jeff "jim bob")
foo "${names[#]}"
For example like this:
my_array[0]="jim"
my_array[1]="jerry"
function foo
{
#get the size of the array
n=${#my_array[*]}
for (( Idx = 0; Idx < $n; ++Idx )); do
echo "${my_array[$Idx]}"
done
}

Resources