Array

An array is a variable that contains multiple values. The number of members starts from 0, there is no upper limit on the number, and there is no requirement for members to be continuously indexed.

Create an array

Arrays can be created by assigning values ​​one by one.

``````ARRAY[INDEX]=value
``````

In the above syntax, `ARRAY` is the name of the array, which can be any legal variable name. `INDEX` is an integer greater than or equal to zero, and it can also be an arithmetic expression. Note that the index of the first element of the array is 0, not 1.

Next, create an array of three members.

``````\$ array[0]=val
\$ array[1]=val
\$ array[2]=val
``````

Arrays can also be created by one-time assignment.

``````ARRAY=(value1 value2 ... valueN)

# Equivalent to

ARRAY=(
value1
value2
value3
)
``````

When using the above method to create an array, you can assign values ​​in the default order, or you can specify the position before each value.

``````\$ array=(abc)
\$ array=([2]=c [0]=a [1]=b)

\$ days=(Sun Mon Tue Wed Thu Fri Sat)
\$ days=([0]=Sun [1]=Mon [2]=Tue [3]=Wed [4]=Thu [5]=Fri [6]=Sat)
``````

It is also possible to specify locations only for certain values.

``````names=(hatter [5]=duchess alice)
``````

In the above example, `hatter` is the 0th position of the array, `duchess` is the 5th position, and `alice` is the 6th position.

The default value of an array element that is not assigned is an empty string.

When defining an array, you can use wildcards.

``````\$ mp3s=( *.mp3)
``````

In the above example, put all MP3 files in the current directory into an array.

It is also possible to declare an array with the `declare -a` command first.

``````\$ declare -a ARRAYNAME
``````

The `read -a` command saves the user's command line input into an array.

``````\$ read -a dice
``````

The above command saves the user's command line input into the array `dice`.

To read the member at the specified position of the array, use the following syntax.

``````\$ echo \${array[i]} # i is the index
``````

The braces in the above grammar are essential, otherwise Bash will output the index part `[i]` as it is.

``````\$ array[0]=a

\$ echo \${array[0]}
a

\$ echo \$array[0]
a[0]
``````

In the above example, the first element of the array is `a`. If you don't increase the brackets, Bash will directly read the value of the first member of `\$array`, and then output `[0]` as it is.

`@` and `*` are special indexes of the array, which means to return all the members of the array.

``````\$ foo=(abcdef)
\$ echo \${foo[@]}
abcdef
``````

These two special indexes can be used to traverse the array with `for` loop.

``````for i in "\${names[@]}"; do
echo \$i
done
``````

There is a difference between `@` and `*` if they are not placed in double quotes.

``````\$ activities=( swimming "water skiing" canoeing "white-water rafting" surfing)
\$ for act in \${activities[@]}; \
do \
echo "Activity: \$act"; \
done

Activity: swimming
Activity: water
Activity: skiing
Activity: canoeing
Activity: white-water
Activity: rafting
Activity: surfing
``````

In the above example, the array `activities` actually contains 5 members, but the `for...in` loop directly traverses `\${activities[@]}`, resulting in 7 results being returned. To avoid this situation, put `\${activities[@]}` in double quotes.

``````\$ for act in "\${activities[@]}"; \
do \
echo "Activity: \$act"; \
done

Activity: swimming
Activity: water skiing
Activity: canoeing
Activity: white-water rafting
Activity: surfing
``````

In the above example, `\${activities[@]}` is placed in double quotes, and the traversal will return the correct result.

`\${activities[*]}` is not enclosed in double quotes, just like `\${activities[@]}` is not enclosed in double quotes.

``````\$ for act in \${activities[*]}; \
do \
echo "Activity: \$act"; \
done

Activity: swimming
Activity: water
Activity: skiing
Activity: canoeing
Activity: white-water
Activity: rafting
Activity: surfing
``````

Put `\${activities[*]}` in double quotes, and all members will be returned as a single string.

``````\$ for act in "\${activities[*]}"; \
do \
echo "Activity: \$act"; \
done

Activity: swimming water skiing canoeing white-water rafting surfing
``````

Therefore, the most convenient way to copy an array is to write it as follows.

``````\$ hobbies=( "\${activities[@]}")
``````

In the above example, the array `activities` is copied to another array `hobbies`.

This way of writing can also be used to add members to a new array.

``````\$ hobbies=( "\${activities[@]" diving)
``````

In the above example, the new array `hobbies` adds another member after all the members of the array `activities`.

Default location

If when reading the array member, the member at the specified position is not read, the position `0` is used by default.

``````\$ declare -a foo
\$ foo=A
\$ echo \${foo[0]}
A
``````

In the above example, `foo` is an array, and the position is not specified when assigning a value. In fact, it is assigning a value to `foo[0]`.

Referencing an array variable without a subscript will refer to the array element at position `0`.

``````\$ foo=(abcdef)
\$ echo \${foo}
a
\$ echo \$foo
a
``````

In the above example, when referencing the array element, the position is not specified, and the result returned is the position `0`.

Length of the array

To know the length of the array (that is, how many members it contains), you can use the following two syntaxes.

``````\${#array[*]}
\${#array[@]}
``````

Below is an example.

``````\$ a[100]=foo

\$ echo \${#a[*]}
1

\$ echo \${#a[@]}
1
``````

In the above example, the string is assigned to the array element at position `100`. At this time, the array has only one element.

Note that if you use this syntax to read a specific array member, the string length of the member will be returned. This must be careful.

``````\$ a[100]=foo
\$ echo \${#a[100]}
3
``````

In the above example, `\${#a[100]}` actually returns the string length of the value (`foo`) of the 100th member of the array `a[100]`.

Extract array number

`\${!array[@]}` or `\${!array[*]}` can return the member number of the array, that is, which positions have values.

``````\$ arr=([5]=a [9]=b [23]=c)
\$ echo \${!arr[@]}
5 9 23
\$ echo \${!arr[*]}
5 9 23
``````

In the above example, the positions 5, 9, and 23 of the array have values.

Using this syntax, you can also loop through the array with `for`.

``````arr=(abcd)

for i in \${!arr[@]};do
echo \${arr[i]}
done
``````

Extract array members

The syntax of `\${array[@]:position:length}` can extract array members.

``````\$ food=( apples bananas cucumbers dates eggs fajitas grapes)
\$ echo \${food[@]:1:1}
bananas
\$ echo \${food[@]:1:3}
bananas cucumbers dates
``````

In the above example, `\${food[@]:1:1}` returns 1 member from position 1 of the array, `\${food[@]:1:3}` returns 3 from position 1 Members.

If the length parameter `length` is omitted, all members starting from the specified position are returned.

``````\$ echo \${food[@]:4}
eggs fajitas grapes
``````

The above example returns all members from position 4 to the end.

Append array members

To append members to the end of the array, you can use the `+=` assignment operator. It can automatically append the value to the end of the array. Otherwise, you need to know the maximum sequence number of the array, which is troublesome.

``````\$ foo=(abc)
\$ echo \${foo[@]}
abc

\$ foo+=(def)
\$ echo \${foo[@]}
abcdef
``````

Delete array

To delete an array member, use the `unset` command.

``````\$ foo=(abcdef)
\$ echo \${foo[@]}
abcdef

\$ unset foo[2]
\$ echo \${foo[@]}
abdef
``````

In the above example, the third element in the array is deleted, and the subscript is 2.

Setting a member to a null value can "hide" this member from the return value.

``````\$ foo=(abcdef)
\$ foo[1]=''
\$ echo \${foo[@]}
acdef
``````

In the above example, the second member of the array is set to an empty string, and this member is "hidden" in the return value of the array.

Note that this is "hidden", not deleted, because this member still exists, but the value becomes a null value.

``````\$ foo=(abcdef)
\$ foo[1]=''
\$ echo \${#foo[@]}
6
\$ echo \${!foo[@]}
0 1 2 3 4 5
``````

In the above code, after the second member is set to a null value, the array still contains 6 members.

Since a null value is an empty string, the following writing also has a hidden effect, but this writing is not recommended.

``````\$ foo[1]=
``````

The above writing is also equivalent to "hiding" the second member of the array.

Assigning the array variable directly to an empty string is equivalent to "hiding" the first member of the array.

``````\$ foo=(abcdef)
\$ foo=''
\$ echo \${foo[@]}
bcdef
``````

The above writing is equivalent to "hiding" the first member of the array.

`unset ArrayName` can empty the entire array.

``````\$ unset ARRAY

\$ echo \${ARRAY[*]}
<--no output-->
``````

Associative array

The new version of Bash supports associative arrays. Associative arrays use strings instead of integers as array indexes.

`declare -A` can declare associative arrays.

``````declare -A colors
colors["red"]="#ff0000"
colors["green"]="#00ff00"
colors["blue"]="#0000ff"
``````

Associative arrays must be declared and created with the `declare` command with the `-A` option. In contrast, for integer-indexed arrays, you can directly use variable names to create arrays, but associative arrays cannot.

The way to access members of an associative array is almost the same as an integer indexed array.

``````echo \${colors["blue"]}
``````