Bash Arrays: Difference between revisions
Line 353: | Line 353: | ||
===Assign Individual Associative Array Elements=== | ===Assign Individual Associative Array Elements=== | ||
Individual elements are initialized by using | Individual elements are initialized by using ''var-name''[''key'']}=''value'' notation: | ||
<syntaxhighlight lang='bash'> | |||
a["color"]="blue" | |||
<syntaxhighlight lang='bash'> | |||
The associative array variable must be declared with -A before, otherwise only the last assignment is reflected in the state of the array. | The associative array variable must be declared with -A before, otherwise only the last assignment is reflected in the state of the array. |
Revision as of 23:10, 19 May 2020
External
- https://www.gnu.org/software/bash/manual/html_node/Arrays.html
- https://opensource.com/article/18/5/you-dont-know-bash-intro-bash-arrays
Internal
Indexed Arrays
External
- http://www.gnu.org/software/bash/manual/html_node/Arrays.html#Arrays
- http://tldp.org/LDP/abs/html/arrays.html
Indexed Arrays Overview
bash indexed arrays are 0-based and unidimensional. No explicit declaration is necessary if at least one element is initialized as described below.
Indexed arrays behave as local variables: an array declared in a function will be accessible to the declaring function and all functions invoked from the declaring function after declaration, but not to callers of the declaring function. In other words, indexed arrays are accessible only in the declaring scope and sub-scopes.
Indexed Arrays Declaration
Arrays do not need explicit declarations, they will be automatically declared upon the first assignment of any of their elements:
my_array_var[0]="something"
They can be explicitly declared, though:
declare -a my_array_var
Previously declared arrays can be listed with:
declare -a
Whether a specific array was declared can be checked as follows:
if declare -a | grep -q my_array_var; then
# 'my_array_var' was declared
...
else
# 'my_array_var' was not declared
...
fi
Negation also works:
if ! declare -a | grep -q my_array_var; then
# 'my_array_var' was not declared
...
else
# 'my_array_var' was declared
...
fi
An indexed array is automatically declared if it is assigned using this syntax:
my_array_var=("a" "b" "c")
An array variable can be "undeclared" with the "unset" builtin.
unset my_array_var
Individual array elements can also be unset:
unset my_array_var[subscript]
A subscript of "*" or "@" also removes the entire array.
Indexed Array Declaration Test
This sequence tests whether a variable was declared as an indexed array. The test does not tell whether the indexed array was actually allocated.
declare -a | grep -q "declare -a my_array" && \
echo "'my_array' was declared as indexed array" || \
echo "'my_array' was not declared as indexed array"
Indexed Array Allocation Test
This sequence tests whether an indexed array was actually allocated (can be empty) and associated with the variable.
[[ -v my_array[@] ]] && \
echo "there is an array associated with 'my_array'" || \
echo "there is NO array associated with 'my_array'"
The above detects allocation in both following cases:
my_array[0]=
my_array[0]="a"
Also see:
Indexed Arrays Assignment
Assign Indexed Array Individual Elements
Individual elements are initialized by using ${var-name[index]}=value notation:
a[0]="something"
Entire Indexed Array
The (value ...) or ([index]=value ...) syntax can be used to initialize an entire array. The values must be separated by space:
a=("X" "Y" "Z")
If we want initialize only specific elements, we can use this syntax:
a=([0]="X" [4]="Y" [8]="Z")
Arrays initialized this way are automatically declared.
Append Array Elements
Use the +=
operator:
declare -a my_array
my_array+=(a)
my_array+=(b)
my_array+=(c)
Load an Array from a Space-Separated List
Method 1 - use a 'for' iterator:
local space_separated_list="a b c d"
declare -a my_array
for i in ${space_separated_list}; do
my_array+=(${i})
done
echo "length: ${#my_array[@]}"
echo ${my_array[0]}
echo ${my_array[1]}
echo ${my_array[2]}
echo ${my_array[3]}
Method 2 - use read:
(note that this can be used for other separators as well, by setting IFS)
local space_separated_list="a b c d"
read -r -a my_array <<< "${space_separated_list}"
echo "length: ${#my_array[@]}"
echo ${my_array[0]}
echo ${my_array[1]}
echo ${my_array[2]}
echo ${my_array[3]}
Read the Content of a File into An Indexed Array
Each line will be assigned to an element of the array:
readarray < ./somefile.txt -t my_array_var
Only the first line will be loaded into the array, where each space separated element will be assigned to an array element:
declare -a VALUES
read -r -a VALUES < ./file.txt
Assign Words Read from stdin to an Indexed Array
Assing words read from stdin to an array:
Indexed Array Access
Dereference the Array Variable
Dereferencing the array variable returns the value of the first element of the array. For
declare -a VALUES
VALUES=("A" "B" "C")
echo ${VALUES}
produces "A".
Indexed Arrays Access by Index
Reference Individual Indexed Array Elements
Element arrays can be referenced with ${var-name[index]} notation:
echo ${a[0]}
If the array variable was not previously declared, or if the specific element was not initialized, a reference attempt will return the blank string.
Reference All Indexed Array Elements
If '@' or '*' is used as subscript, the following expressions expand to all members of the array:
${var_name[@]} ${var_name[*]}
Reference a Sub-Array
A contiguous sub-array can be referenced as follows:
${var_name[@]:from}
returns all elements of the array starting with the index 'from'.
${var_name[@]:from:to}
returns all elements of the array starting with the index 'from' up to index 'to'.
Indirect Variable Access for Indexed Arrays
It is possible to use variable indirection with indexed array variables. Knowing the name of the array variable, the values corresponding to a certain index can be accessed as follows:
declare -a VALUES
VALUES=("A" "B" "C")
The value of the first element of the array is displayed as follows:
name="VALUES[0]"
echo ${!name}
The value of the second element of the array is displayed as follows:
name="VALUES[1]"
echo ${!name}
Length of an Indexed Array
${#var_name[@]} ${#var_name[*]}
If the array is sparse, this does not return the index of last element plus one, but just the number of non-empty elements.
Iterate over an Indexed Array
Using the Indexed Array Elements
for i in ${array_var[@]}; do ... done
Using the Index
i=0 while [[ ${i} < ${#array_var[@]} ]]; do echo ${array_var[$i]} ((i++)) done
Note that this does not work when the array is sparse, because ${#array_var[@]} only returns the number of non-empty elements, and not the array length.
Clear an Indexed Array
Note that re-declaring an indexed array does not clear it. To be cleared, the array needs to be unset and redeclared.
declare -a A
...
unset A
declare -a A
Indexed Array Use Cases
Iterate Over the Argument List
args=("$@") for arg in ${args[@]}; do ... done
Associative Arrays
Associative Array Overview
Associative arrays can be used to implement sets and maps in bash. The most common usage as set is to insert elements whose subscript is identical with the value.
Associative Array Declaration
Associative arrays must be explicitly declare before initialization, otherwise unexpected behavior may occur. For example, if multiple assignments are declared, only the last one is reflected in the state of the array. This is different from the behavior of the indexed arrays, which can be used without explicit declaration.
declare -A my_assoc_array
This command does not create the associative array immediately, it just sets an attribute on the name "my_assoc_array" which allows assignments to the name as an associative array. The array does not exist until the first assignment. The fact that a specific array was declared can be tested by executing declare -A
and grepping the result, as shown below.
All previously declared (and not yet unset) associative arrays can be listed with:
declare -A
An associative array variable can be "undeclared" with the "unset" builtin.
unset my_assoc_array
Associative Array Declaration Test
This sequence tests whether a variable was declared as an associative array. The test does not tell whether the associative array was actually allocated.
declare -A | grep -q "declare -A my_assoc_array" && \
echo "'my_assoc_array' was declared as associative array" || \
echo "'my_assoc_array' was not declared as associative array"
Associative Array Allocation Test
This sequence tests whether an associative array was actually allocated (can be empty) and associated with the variable.
[[ -v my_assoc_array[@] ]] && \
echo "there is an array associated with 'my_assoc_array'" || \
echo "there is NO array associated with 'my_assoc_array'"
The above detects allocation in both following cases:
my_assoc_array["a"]=
my_assoc_array["a"]="b"
Also see:
Associative Array Assignment
Assign Individual Associative Array Elements
Individual elements are initialized by using var-name[key]}=value notation:
a["color"]="blue"
<syntaxhighlight lang='bash'>
The associative array variable must be declared with -A before, otherwise only the last assignment is reflected in the state of the array.
===Entire Associative Array===
The (["key"]="value" ...) syntax can be used to initialize an entire array. The values must be separated by space:
a=(["color]="red" ["size"]="small")
==Associative Array Key Existence==
The existence of a specific key in an associative array (whether it has a value associated with it or not) can be tested with:
<syntaxhighlight lang='bash'>
declare -A A
[[ ${A["some-key"]+nonemptystring} ]] && echo "'some-key' exists" || echo "'some-key' does not exist"
The key is identified to exist even if it has an empty value. In the following cases, the key is identified as existent:
A["some-key"]=
A["some-key"]=""
A["some-key"]="something"
This should work for both associative arrays and indexed arrays.
More general:
declare -A A
key="somekey"
A[${key}]="somevalue"
[[ ${A[${key}]+nonemptystring} ]] && echo "'${key}' exists" || echo "'${key}' does not exist"
Associative Array Reference
Reference Individual Associative Array Elements
Element arrays can be referenced with ${var-name[key]} notation:
echo ${a["color"]}
If the array variable was not previously declared, or if the specific element was not initialized, a reference attempt will return the blank string.
Get All Associative Array Keys
The keys are accessed with:
${!array_var_name[@]}
Get All Associative Array Values
If '@' or '*' is used as subscript, the following expressions expand to all values maintained in the array:
${array_var_name[@]} ${array_var_name[*]}
Iterate over Key/Values of an Associative Array
for k in "${!array_var_name[@]}"; do
echo "key: ${k}"
echo "value: ${array_var_name[${k}]}"
done
Enclose ${!array_var_name[@]} in double quotes.
Size
${#var_name[@]} ${#var_name[*]}
Clear the Array
To clear an individual element of the array, use:
unset array_name[subscript]
declare -a a
a["color"]="blue"
unset a["color"]
To clear the entire array, but not discard the variable, iterate over the array and unset each element:
for k in "${!array_var_name[@]}"; do
unset array_var_name[${k}]
done
Enclose ${!array_var_name[@]} in double quotes.