0

How do I create n variables in shell scripts without explicitly assigning them? What I mean is something like a loop that creates var1, var2, var3,...,varx, where x is a variable I set earlier, something like:

read x

for ((a=0;a<x;++a)); do
 variable$a=${RANDOM}
done

(Let's ignore the possibility that x might be a string for now. But obviously, this doesn't work. How would one do this?

What I actually want to do, is that each argument I wrote in the command line when I executed the script to become it's own variable ARG1, ARG2... ARGn with ${1}, ${2},..., ${n} as its value, so there will only be as many of these variables, as arguments were set.

1
  • 3
    Why do you need to do this?
    – muru
    Aug 22, 2018 at 9:19

4 Answers 4

2

It looks like you want to use an array:

read x

for (( a=0; a<x; ++a)); do
   variable[a]=$RANDOM
done

printf 'First value is %s\n' "${variable[0]}"

printf 'All values (one by one): %s\n' "${variable[@]}"
printf 'All values (as one string): %s\n' "${variable[*]}"

For the second part of your question:

arg=( "$@" )

printf 'First command line argument: %s\n' "${arg[0]}"

Note also that you can easily loop over all command line arguments (or whatever happens to be in $@) without storing them anywhere special:

for arg do
    printf 'Got command line argument: %s\n' "$arg"
done
6
  • But isn't an array just one variable but with multiple values? Would that work for what I'm trying to do? (assign each argument as it's own variable)
    – iamAguest
    Aug 22, 2018 at 9:12
  • 1
    @iamAguest How would you go about using these multiple variables? You would end up with very messy code if you tried to create multiple variables. An array is the proper way to store an indeterminate amount of separate values in any programming language.
    – Kusalananda
    Aug 22, 2018 at 9:14
  • @iamAguest, is there some essential difference? If you would name them var1, var2 etc., you might as well name them var[1], var[2] etc. The workarounds for not using arrays are seriously ugly.
    – ilkkachu
    Aug 22, 2018 at 9:20
  • Ah I see, that's really cool, but then, how would I go about doing arithmetic with every value in the array? So something I actually wanted was to have the arguments for the script be all integers, and I would be able to add them all together, something like argtotal=$((arg1+arg2+arg3+...+argn)); echo "$argtotal"
    – iamAguest
    Aug 22, 2018 at 9:26
  • @iamAguest That particular question has been asked a number of times before. See e.g. How do I create a bash script that sums any number of command line arguments?
    – Kusalananda
    Aug 22, 2018 at 9:27
1

Try this,

read x

for ((a=0;a<x;++a)); do
 declare -i variable$a=${RANDOM}
done

declare command permits assigning a value to a variable in the same statement as setting its properties.

0

You need to eval the assignment (but to use an array would be better).

#!/bin/bash -vx

read x
for ((a=0;a<x;++a)); do
   eval variable$a=${RANDOM}
done

From man bash

eval [arg ...]
    The args are read and concatenated together into a single command. 
    This command is then read and executed by the shell, and its exit 
    status is returned as the value of eval.
5
  • In this case, $a must be a number, so it can't contain any extra expansions (which eval would process), so you're sort of safe. But really, if you're running in Bash, why would you ever use eval instead of an array in a simple case like this? The mess it potentially produces is just too big.
    – ilkkachu
    Aug 22, 2018 at 9:23
  • @ilkkachu I agree that it is a weak solution. But, for example, I used this to initialize some configuration variables, reading a json file (from a remote service) without knowing the needed variable names (to prepare the environment to a legacy software). I remember I needed a lot of checks to avoid word splitting.
    – andcoz
    Aug 22, 2018 at 9:30
  • Yeah, that would be different. Though as another answer reminds, even that could be done with typeset (or declare) instead of eval, e.g. name=foo; value=bar; typeset "$name=$value"; echo $foo prints bar.
    – ilkkachu
    Aug 22, 2018 at 9:36
  • @ilkkachu, except that declare/typeset also have the side effect of reducing the scope of the variable. Aug 22, 2018 at 11:23
  • 1
    Note that there is a command injection vulnerability here, the same as in all the other answers, because $x is evaluated as an arithmetic expression in for ((...)), not because of eval. Try for instance echo 'a[$(uname>&2)0]' | bash -c 'read x; for ((i = 0; i < x; i++)); do : ;done'. By the way declare/typeset (even read in bash) can introduce ACEs the same as eval (not here as the content of $a is controller). They do also evaluate code. Aug 22, 2018 at 11:34
0

How about (recent shell needed)

 for ((a=0;a<x;++a))
   do  read variable$a <<<${RANDOM}
   done

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .