0

I'll try to explain:

I'm writing a bash script and I'm within a for loop. For all loops, I got a variable VAR_ID, that is used to store an identifier for another variable that will be exported when all work is done. For each single loop, I got a variable VAL. VAL's value should be assigned to VAR_ID's value. In the end, VAR_ID's value has to be an array in order to store all values.

Phew... well, it's a bit hard to explain for me, but I think this simple script should clarify what I'm trying to do (it's narrowed down from its actual purpose of course):

#!/bin/bash

COUNT=0
VAR_ID="my_array"
declare -a "$VAR_ID"

while (( $COUNT <= 2 ))
do
    VAL=$RANDOM
    $VAR_ID+=( "$VAL" )    # this doesn't work
    (( COUNT++ ))
done

export $VAR_ID

This should result in a variable my_array and three random values in it. I tried using declare as in declare $VAR_ID=$VAL, but this doesn't work anymore if I use += instead of =. COUNT can be used in a possible solution as position number or so if it helps as I have it also in my original script.

Thanks for any help in advance

Edit: I know there is a possibility with eval but I try to avoid using that until there is no other way.

Dewdrop
  • 13
  • 5
  • See [this answer](/a/55331060/10248678), tl;dr: make VAR_ID a nameref. – oguz ismail Mar 08 '21 at 14:28
  • Maybe I don't understand what you mean. But a nameref doesn't really help as I'm already able to address the right values. It fails at the part where I'm trying to build an array named `$VAR_ID` using `+=` and `declare`. So my own solution, or should I call it workaround, is all about either using `+=` or `declare`, but not both at the same time because that fails. – Dewdrop Mar 10 '21 at 16:48
  • That's exactly where the nameref is supposed to help. If you do `declare -n VAR_ID=my_array` at the beginning, `VAR_ID+=(whatever)` will add `whatever` to the array named `my_array`, and `export "${!VAR_ID}”` would export `my_array` if bash could export arrays, but it can't. – oguz ismail Mar 10 '21 at 19:29

2 Answers2

0

I'm not sure what you're trying to do exactly, but you could use an associative array and export that. You can access elements of an associative array with variables in bash.

#!/usr/bin/env bash
declare -Ax arr # declare and export an associative array named 'arr'
declare -x var_id='array_position' # declare and export a variable named 'var_id'

for((i=0; i<=2; i++)); do
    val=${RANDOM}
    arr["${var_id}"]="${val}" # assign to the associative array with the var_id variable being the key, and val being the value
done

You can then access the associative array with variables, strings, or by iterating through it.

# Using an exact key name
echo "${arr[array_position]}"
# Using a variable which points to the key name
echo "${arr[${var_id}]}"
# Using a for loop
for key in "${!arr[@]}"; do
    value="${arr[${key}]}"
    echo "${key} ${value}"
done

From the bash manpage

When assigning to an associative array, the words in a compound assignment may be either assignment statements, for which the subscript is required, or a list of words that is interpreted as a sequence of alternating keys and values: name=(key1 value1 key2 value2 … ). These are treated identically to name=( [key1]=value1 [key2]=value2 … ). The first word in the list determines how the remaining words are interpreted; all assignments in a list must be of the same type. When using key/value pairs, the keys may not be missing or empty; a final missing value is treated like the empty string.

This syntax is also accepted by the declare builtin. Individual array elements may be assigned to using the name[subscript]=value syntax introduced above.

644
  • 629
  • 4
  • 14
  • That doesn't address my problem, but no hate, because it's somehow hard to explain for me. It is expected that `$VAR_ID` (`my_array` in that specific case above) is the array at the end, in which all the `$VAL`s (some random numbers, but it can be anything) are stored, not some position identifier within an array that is always called `arr` or whatever. But I provided a solution by myself. Unfortunately I'm not able to post it as answer anymore. – Dewdrop Mar 10 '21 at 16:55
0

Here is an answer for my own question for anyone who encounters the same problem:

#!/bin/bash

COUNT=0
VAR_ID="my_array"
declare PSEUDOARRAY    # is actually just a list of strings separated by spaces

while (( $COUNT <= 2 ))
do
    VAL=$RANDOM
    PSEUDOARRAY+="$VAL "
    (( COUNT++ ))
done

declare -agx $VAR_ID='( $PSEUDOARRAY )'    # "cast" PSEUDOARRAY on an actual array

This solves my problem. Note that if you don't do the "cast" part at the end an just use VAR_ID directly, the resulting my_array doesn't provide things like ${my_array[0]} to give only the first item or ${#my_array[@]} to count the items.

Also note: This method is limited as it does not distinguish between separator spaces and "value spaces" that may be stored in VAL.

Dewdrop
  • 13
  • 5