Bash array with variable in the name

arraybashvariable

I'll appreciate your help with the following issue:

I'm trying to set an array which contains a variable as part of the array name, example: Arr_$COUNTER (where $COUNTER is changed based on a loop count)

Every possible way I have tried came up with an error, such as "bad substitution" or "syntax error near unexpected token"

Here is the entire flow:

  1. There is one file which contain multiple lines. each line has 6 values separated by space

    10 20 30 40 50 60  
    100 200 300 400 500 600
    
  2. The script, is meant to read each line from the file, and declare it as an array (with the line number which is the variable.

  3. as a test, each value should be printed and eventually another function will be executed on each value.

    #!/bin/bash
    COUNTER=1
    LINES=`wc -l VALUES_FILE.txt | awk '{print $1}'`
    echo "Total number of lines "$LINES
    echo
    while [ $COUNTER -le $LINES ]
    do
    echo "Counter value is $COUNTER"
    field=`awk "NR == $COUNTER" VALUES_FILE.txt`
    echo "Field = $field"
    declare -a "arr$COUNTER=($field)"
    echo "arr$COUNTER[0] = ${arr$COUNTER[0]}"
    echo "arr$COUNTER[1] = ${arr$COUNTER[1]}"
    echo "arr$COUNTER[2] = ${arr$COUNTER[2]}"
    echo "arr$COUNTER[3] = ${arr$COUNTER[3]}"
    echo "arr$COUNTER[4] = ${arr$COUNTER[4]}"
    echo "arr$COUNTER[5] = ${arr$COUNTER[5]}"
    let COUNTER=COUNTER+1
    echo
    done
    echo "The End"
    echo
    

Here is the result:

Total number of lines 2

Counter value is 1
Field = 10 20 30 40 50 60
./sort.sh: line 12: arr$COUNTER[0] = ${arr$COUNTER[0]}: bad substitution
The End

What should be changed / fixed in order to have it working properly?

thank !

Best Answer

Some ideas:

  1. A "parameter expansion" of a variable value (the ${...} part):

    echo "arr$COUNTER[0] = ${arr$COUNTER[0]}"
    

    will not work. You may get around by using eval (but I do not recommend it):

    eval echo "arr$COUNTER[0] = \${arr$COUNTER[0]}"
    

    That line could be written as this:

    i="arr$COUNTER[0]"; echo "$i = ${!i}"
    

    That is called indirection (the !) in Bash.

  2. A similar issue happens with this line:

    declare -a "arr$COUNTER=($field)"
    

    Which should be split into two lines, and eval used:

    declare -a "arr$COUNTER"
    eval arr$COUNTER\=\( \$field \)
    

    Again, I do not recommend using eval (in this case).

  3. As you are reading the whole file into the memory of the shell, we may as well use a simpler method to get all lines into an array:

    readarray -t lines <"VALUES_FILE.txt"
    

    That should be faster than calling awk for each line.

An script with all the above could be:

#!/bin/bash
valfile="VALUES_FILE.txt"

readarray -t lines <"$valfile"             ### read all lines in.

line_count="${#lines[@]}"
echo "Total number of lines $line_count"

for ((l=0;l<$line_count;l++)); do
    echo "Counter value is $l"             ### In which line are we?
    echo "Field = ${lines[l]}"             ### kepth only to help understanding.
    k="arr$l"                              ### Build the variable arr$COUNTER
    IFS=" " read -ra $k <<<"${lines[l]}"   ### Split into an array a line.
    eval max=\${#$k[@]}                    ### How many elements arr$COUNTER has?
    #echo "field $field and k=$k max=$max" ### Un-quote to "see" inside.
    for ((j=0;j<$max;j++)); do             ### for each element in the line.
        i="$k[$j]"; echo "$i = ${!i}"      ### echo it's value.
    done
done
echo "The End"
echo

However, still, AWK may be faster, if we could execute what you need in AWK.


A similar processing could be done in awk. Assuming the 6 values will be used as an IP (4 of them) and the other two are a number and an epoch time.

Just a very simple sample of an AWK script:

#!/bin/sh
valfile="VALUES_FILE.txt"
awk '
NF==6 { printf ( "IP: %s.%s.%s.%s\t",$1,$2,$3,$4)
        printf ( "number: %s\t",$5+2)
        printf ( "epoch: %s\t",$6)
        printf ( "\n" )
    }
' "$valfile"

Just make a new question with the details.

Related Question