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.

Read array

Read a single element

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.

Read all members

@ 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"]}