-1

I am stuck with the below code and any help would be greatly appreciated:

I am trying to assign contents inside a dynamically generated variable to another variable. But instead of the value of the variable getting assigned, I could see that the variable name is getting assigned. I tried (echo/eval/!) but nothing is working. Could someone please help me with the solution?

Objective: To assign value 24 (saved under variable msd_ext_len) to final_count variable.

Variable Declaration

iter_val=1

var_1="msd_ext"

msd_ext_len=24

Code:

eval "final_count"=\${var_${iter_val}}_len

Output --> msd_ext_len

Expected Output --> 24

If I add one more line of code as shown below along with above code and I am getting the output:

count_val=${!final_count}

But can these 2 lines of code be clubbed into a single line of code?

ilkkachu
  • 138,973
  • What kind of a data structure do you have? iter_val sounds like you have a bunch of different values, indexed by a number, like an array in C or Python. But then you have the variable name msd_ext stored in a variable too, is that something like different properties of the objects in that array, or something else? The shell doesn't really make this sort of thing easy, and I'm not sure how to interpret your example since you only show assignment to one particular value. – ilkkachu Mar 14 '20 at 15:56
  • Actually this is part of huge shell script. The existing script has multiple if else conditions and based on each condition, script assigns different values to fee variables. Now I am trying to avoid those if else conditions to a single function with arguments passed. And based on the arguments variable name will be generated and values – Mohammed Haleem S Mar 14 '20 at 16:01
  • Example: i have 3 different source data. Based on those 3 types of input, a set of variables are generated and values are assigned. Currently we have an if elif elif else structure. Since variable name changes with source, i am trying to generate variable names dynamically and its values.. these values will be passed to loop and generate few results accordingly. – Mohammed Haleem S Mar 14 '20 at 16:04
  • What i am looking for how I can club below 2 code snippets:
    eval "final_count"=${var_${iter_val}}_len ; count_val=${!final_count}
    – Mohammed Haleem S Mar 14 '20 at 16:08
  • all in all, that sounds like something that could do with the data structures being sketched out in terms of objects and their properties, and arrays/lists whatever. And thinking about how to implement them in Bash, preferably using features it provides, like actual arrays. Or just doing the whole thing in say Python, it might well end up easier for complicated data structures. – ilkkachu Mar 14 '20 at 16:10

1 Answers1

1

So, first, every time you do something like ${var_${iter_val}}, i.e. trying to append a number to a variable name, you should be using an array instead:

arr=(a b c)
arr[1]=x
i=1
echo "${arr[i]}"

If you need to have something indexed by strings instead, use an associative array (declare -A arrayname in Bash).

The combination of those, say having distinct properties on some "objects" in an array, is harder. You could use two separate arrays and then use foo[i] and bar[i].

If you still need to indirectly point to those arrays by name, you need a name reference.

foo=(a b c)
bar=(x y z)
declare -n arrname=foo
echo "${arrname[i]}"

I can't tell from your code what your data structure is supposed to be, exactly, so it's hard to give an answer for just that scenario.


Trying to rewrite your example, you could do something like this:

varnames=()
varnames[1]=msd_ext
varnum=1
msd_ext_len=24

declare -n srcvar="${varnames[varnum]}_len"
declare -n dstvar=final_count
dstvar=$srcvar

echo $final_count

That still requires using an array for varnames, since the nested expansion ${var_$foo} doesn't really work.

See:

ilkkachu
  • 138,973
  • as per above code snippet if i execute echo ${srcvar} , the output I get is msd_ext_len. If i execute echo ${!srcvar}, then only I am getting the expected final results. – Mohammed Haleem S Mar 14 '20 at 16:22
  • I am expecting srcvar to store final results and not the variable name. – Mohammed Haleem S Mar 14 '20 at 16:23
  • @MohammedHaleemS, hmm no, with the declare -n, any references to srcvar should take the value of the variable named there, pretty much like ${!srcvar}. If I run that snippet in a clean shell, it assigns 24 to final_count and outputs that. – ilkkachu Mar 14 '20 at 16:26
  • I am getting the below error: -bash: declare: -n: invalid option declare: usage: declare [-aAfFilrtux] [-p] [name[=value] ...] – Mohammed Haleem S Mar 14 '20 at 16:37
  • Can you please let me know if you can help me combine below 2 lines of code into a single line of code:

    line 1--> eval "temp"=${var_${iter_val}}_result; /assigns "final_result" as value to temp variable/

    line 2--> dist=${!temp}; /assigns 100 as the value to dist variable/

    where

    iter_val=1

    var_1="final"

    final_result=100

    – Mohammed Haleem S Mar 14 '20 at 16:42
  • @MohammedHaleemS, well, yeah, namerefs were added in Bash 4.3, somewhere around 2014. – ilkkachu Mar 14 '20 at 16:44
  • Can you please let me know if you can help me combine below 2 lines of code into a single line of code:

    line 1--> eval "temp"=${var_${iter_val}}_result; /assigns "final_result" as value to temp variable/

    line 2--> dist=${!temp}; /assigns 100 as the value to dist variable/

    where iter_val=1, var_1="final", final_result=100

    – Mohammed Haleem S Mar 14 '20 at 16:49