Array in Script

Reference:

The first thing to do is to distinguish between bash indexed array and bash associative array. The former are arrays in which the keys are ordered integers, while the latter are arrays in which the keys are represented by strings.

Although indexed arrays can be initialized in many ways, associative ones can only be created by using the declare command.

Create Indexed Array

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# create array with out declare
# 注意这里index 只能是number,否则会出问题,因为associated array 必须用declare -A先声明
array=([0]=Sun [1]=Mon [100]=Tue [3]=Wed [4]=Thu [5]=Fri [6]=Sat)
# or
array=(
x
y
z
)
# create array via declare
declare -a array=(x y z)
# create separately
declare -a array
# the same as array=xx
array[0]=xx
array[1]=yy
array[8]=zz

# print
declare -p array
# delete item
unset array[2]
# empty and delete the array
unset array
# this will not have any impact on array content
array=

Add new element into array:

1
2
3
array+=(${var})
# or multi-item
array+=('foo' 'cat')

Note that in the context where an assignment statement is assigning a value to a shell variable or array index (see Arrays), the += operator can be used to append to or add to the variable’s previous value.

Using "${array[@]}"(have double quotes) in for loop to fetch array item. "${array[*]}" is not recommended, the same reason as shell positional parameters with @ and *.

1
2
3
4
for item in "${array[@]}"
do
echo ${item}
done

Or fetch item by index(key):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# this will only return the value existed index
# the same as associated array iteration, but here it returns index number instead
for i in "${!array[@]}"
do
# ${array[i]} also OK
echo ${array[$i]}
done

# ${#array[@]}: length of array
# but it bash array may have gaps! some items are empty
for((i=1;i<${#array[@]};i++))
do
echo ${array[i]}
echo ${array[i-1]}
done

Sort array, 这里对array的输出使用了pipeline,一个很好的启发:

1
2
3
4
5
6
a=(f e d c b a)

echo "Original array: ${a[@]}"
# out most () is for forming a array
a_sorted=($(for i in "${a[@]}"; do echo $i; done | sort))
echo "Sorted array: ${a_sorted[@]}"

Create Associated Array

Statement declare is the only way to go, see reference for more details. Actually this is Map in bash. 这里的key 默认是string,虽然可以写成数字.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# create all at once
declare -A array=([a]=xx [b]=yy [c]=zz)
# create separately
declare -A array
array[a]=xx
array[b]=yy
array[c]=zz
# or write in one line
# 注意这里先declare -A 了
array=([a]=xx [b]=yy [c]=zz)

# print
declare -p array
# delete item
unset array[2]
# empty and delete array
unset array
# this will not have any impact on array content
array=

Iterate over the associated array:

1
2
3
4
5
6
7
8
9
10
11
12
13
declare -a array=([a]=a [b]=b [c]=c)
# The keys are accessed using an exclamation point
# can do this to index array as well!
for key in "${!array[@]}"
do
echo "key : $key"
echo "value: ${array[$key]}"
done

# assign all keys to other array
array2=("${!array[@]}")
# copy whole array
array3=("${array[@]}")

Array Counterpart

Loop through comma separated string, or other delimiter.

1
2
3
4
5
6
7
8
var="1,2,3,4,5"
# use sed
for i in $(echo $var | sed "s/,/ /g")
# or use pattern match
for i in ${var//,/" "}
do
echo $i
done

还可以使用IFS设置不同的separator (IFS also is used with read), 也可以用tr去替换分隔符。

Caveat

If you use declare -a or declare -A to create array in shell function, it by default is local scope in that function. You can move the declare out to make the array globally access, or use declare -ga and `declare -gA (only bash 4.2 and later support this).

Notice that variable defined without local in function is global access.

Assign array to other variables:

1
2
3
a=('a' 'b' 'c')
# must have double qoutes to protect key that has whitespace
b=("${a[@]}")

Notice that you cannot export array directly. Array variables may not (yet) be exported. in some bash verions, but there are some workarounds.

References

Bash associative array examples Bash indexed arrays Indexed and associative array

0%