I just want to show a slightly more-thorough version of Eric Renouf's answer to make it crystal clear how you can dynamically generate a variable name from multiple other variables and then access the contents of that new, dynamically-generated variable.
some_variable="Hey how are you?"
# the 1st half of the variable name "some_variable"
var1="some"
# the 2nd half of the variable name
var2="variable"
# dynamically recreate the variable name "some_variable", stored
# as a string inside variable `var3`
var3="${var1}_${var2}"
Now look at these outputs:
echo "${var3}"
outputs:
some_variable
BUT this (the exact same as above except we added the ! char just before the variable name is all):
echo "${!var3}"
outputs:
Hey how are you?
It's magical!
It's as though we had a C macro where we had echo "${${var3}}" which expanded to echo "${some_variable}" which then became Hey how are you?.
That syntax would be invalid, however, and you'd get this error:
$ echo "${${var3}}"
bash: ${${var3}}: bad substitution
You can do this echo "${!var3}" trick in place of using eval, since eval is considered "dangerous" and "evil". For understanding and education though, here is the equivalent way to do this with eval instead:
$ eval echo "\$${var3}"
Hey how are you?
versus:
$ echo "${!var3}"
Hey how are you?
eval echo "\$${var3}" expands to eval echo "$some_variable", which has the same output:
$ eval echo "$some_variable"
Hey how are you?
But, even though eval echo "\$${var3}" and echo "${!var3}" produce the exact same result in this case (the Hey how are you? output), apparently the eval version is evil and the ! version is good.
You can read the "good" version (echo "${!var3}") as follows (in my own words):
echoing "$var3" means: "output the contents of the var3 variable." BUT, echoing "${!var3}" means: "output the contents of what the var3 variable contains, assuming its contents are the name to another variable!"
The ! in bash here is kind of like dereferencing a pointer in C with the * character like this!:
*some_ptr
It adds an extra layer of abstraction.
Related
- Note that the need for this - !trick can frequently be avoided using associative arrays in bash. Associative arrays are essentially "hash tables", which are called "unordered maps" in C++ and "dicts" (dictionaries) in Python. Here are a few relevant links on them:
 - 
- https://stackoverflow.com/questions/6149679/multidimensional-associative-arrays-in-bash
- [VERY GOOD TUTORIAL!] *****https://www.artificialworlds.net/blog/2012/10/17/bash-associative-array-examples/
 - Keep in mind, however, that associative arrays (and all other arrays too) in bash are 1-dimensional! From - man 1 bash(emphasis added):
 - 
- Arrays - Bash  provides one-dimensional indexed and associative array variables.  Any variable may be
used as an indexed array; the declare builtin will explicitly declare an array.  There is no
maximum  limit  on  the  size  of  an  array, nor any requirement that members be indexed or
assigned contiguously.  Indexed arrays are referenced using integers  (including  arithmetic
expressions)  and are zero-based; associative arrays are referenced using arbitrary strings.
Unless otherwise noted, indexed array indices must be non-negative integers. - An indexed array is created automatically if any variable is assigned to  using  the  syntax
name[subscript]=value.  The subscript is treated as an arithmetic expression that must eval‐
uate to a number.  To explicitly declare an indexed array, use declare -a  name  (see  SHELL
BUILTIN  COMMANDS  below).   declare  -a  name[subscript] is also accepted; the subscript is
ignored. - Associative arrays are created using declare -A name. - Attributes may be specified for an array variable using the declare and  readonly  builtins.
Each attribute applies to all members of an array. - Arrays  are  assigned  to  using  compound assignments of the form name=(value1 ... valuen),
where each value is of the  form  [subscript]=string.   Indexed  array  assignments  do  not
require anything but string.  When assigning to indexed arrays, if the optional brackets and
subscript are supplied, that index is assigned  to;  otherwise  the  index  of  the  element
assigned is the last index assigned to by the statement plus one.  Indexing starts at zero. - When assigning to an associative array, the subscript is required. 
 
 
    
FIRST=$(( $6 + 1 ))