linux 数组

前言

本文为作者原创作品,转载请注明出处;

一维数组

基础

  • 定义
    两种定义的方式

    1
    arr=(Hello World)

    或者

    1
    2
    arr[0]=Hello
    arr[1]=World
  • 输出

    1
    2
    $ echo ${arr[0]} ${arr[1]}
    Hello World

    为什么要使用 \${} 的符号来定义数组元素的输出呢?官文是这样解释的,

    The braces are required to avoid conflicts with pathname expansion.

    意思是说,为了避免与“路径名”发生冲突;

  • 其它重要属性

    1
    2
    3
    4
    5
    ${arr[*]}         # 返回 array 中的所有元素
    ${arr[0]} # 返回指定下标的数组元素
    ${!arr[*]} # 返回 array 中的所有坐标
    ${#arr[*]} # 返回 array 中的元素个数,也就是数组长度
    ${#arr[0]} # 返回第 0 个元素自身的长度

    看一些例子,假设我们有 array arr 如下,

    1
    arr=(Hello World)
    1. ${arr[*]},依次返回数组中的元素

      1
      2
      $ echo ${arr[*]}
      Hello World

      注意,这里是依次返回并挨个打印出 item 的,因此,${arr[*]}的输出是可以被迭代的,因此,

      1
      2
      3
      4
      5
      echo "Array items:"
      for item in ${arr[*]}
      do
      printf " %s\n" $item
      done

      输出,

      1
      2
      Hello
      World
    2. ${!arr[*]},依次返回元素的坐标

      1
      2
      3
      4
      5
      echo "Array indexes:"
      for index in ${!arr[*]}
      do
      printf " %d\n" $index
      done

      输出,

      1
      2
      0
      1
    3. 输出队列的长度

      1
      2
      $ echo "Array size: ${#arr[*]}"
      2
    4. 输出某个元素的长度

      1
      2
      $ echo "Array size: ${#arr[0]}"
      5
    5. 迭代数组,并同时输出坐标和值

      1
      2
      3
      4
      5
      echo "Array items and indexes:"
      for index in ${!arr[*]}
      do
      printf "%4d: %s\n" $index ${arr[$index]}
      done

      输出,

      1
      2
      0: Hello
      1: World
  • 最后,这里要注意一下的是,通过 index 的遍历和直接通过元素遍历的异同,假设,我们有数组,

    1
    array=("first item" "second item" "third" "item")
    • 通过 index 遍历我们将得到的是 4 个元素

      1
      2
      3
      4
      5
      echo "Number of items in original array: ${#array[*]}"
      for ix in ${!array[*]}
      do
      printf " %s\n" "${array[$ix]}"
      done

      输出,

      1
      2
      3
      4
      first item
      second item
      third
      item

      可以看到,分别返回总共 4 个元素

    • 通过直接元素遍历,我们将得到的是 6 个元素

      1
      2
      3
      4
      for a in ${array[*]}
      do
      printf " %s\n" "$a"
      done

      输出,

      1
      2
      3
      4
      5
      6
      first
      item
      second
      item
      third
      item

      所以,当我们如果要将双引号内的元素视为一个 item 元素的时候,使用 index 遍历元素,如果我们不讲双引号内的元素单独视为一个 item,而是按照空格的方式来计算,那么使用直接元素遍历的方式

@ 符号

大多数情况下,在数组的表达始终,@ 和 * 等价,比如,

1
2
3
4
$ echo ${arr[@]}
Hello World
$ echo ${#arr[@]}
2

但是,在当使用到 double quoted 既双引号表达式的时候,@ 和 * 有不同的地方;比如,"${arr[*]}" 是将结果作为一个字符串整体返回,而 "${#arr[@]}" 是将数组中的元素逐个进行返回的;看下面的例子,

1
2
3
$ new_arr=("${arr[*]}")
$ echo "array length: ${#new_arr[*]}"
array length: 1

可以看到,"${#arr[*]}" 是将 arr 数组的内容作为一个元素(字符串)进行返回的。

下面看看 "${#arr[@]}" 的情况,
1
2
3
$ new_arr=("${arr[@]}")
$ echo "array length: ${#new_arr[*]}"
array length: 2

可以看到,它是将数组中的元素挨个返回的,可以对结果进行迭代,

1
2
3
4
5
new_arr=("${arr[@]}")
for ix in ${!new_arr[*]}
do
printf " %s\n" "${new_arr[$ix]}"
done

输出

1
2
Hello
World

二维数组

我们如何通过 @ 的方式构建出二维数组的计算方式呢?假设,我们有数组定义如下,

1
array=("A1 A2" "B1 B2" "C1 C2" "D1 D2")

  • 结合 index 遍历和直接遍历的方式,

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    for i in ${!array[*]}
    do
    v=${array[$i]} # 得到单个元素 "A1 A2"
    printf "single element: \"%s\"\n" "$v"
    arr=($v) # 将 "A1 A2" 元素构建成一维数组
    printf "inner item1: %s, inner item2: %s\n" "${arr[0]}" "${arr[1]}"
    for v in ${arr[*]} # 直接元素遍历
    do
    printf "iterate inner item: %s\n" "$v"
    done
    done

    输出,

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    single element: "A1 A2"
    inner item1: A1, inner item2: A2
    iterate inner item: A1
    iterate inner item: A2
    single element: "B1 B2"
    inner item1: B1, inner item2: B2
    iterate inner item: B1
    iterate inner item: B2
    single element: "C1 C2"
    inner item1: C1, inner item2: C2
    iterate inner item: C1
    iterate inner item: C2
    single element: "D1 D2"
    inner item1: D1, inner item2: D2
    iterate inner item: D1
    iterate inner item: D2

    可见,我们成功的将这种二维数组,(“A1 A2” “B1 B2” “C1 C2” “D1 D2”),中的元素进行了遍历,它主要是结合了一维数组的 index 比那里和直接遍历的特性进行的,通过 index 遍历,将双引号内部的内容视为一个元素,然后将该元素通过一维数组的定义方式,转化为另一个一维数组,最后通过一维数组直接遍历的方式遍历出二维数组既 inner item 的内容;

有时候为了便于配置,可以将二维数组的定义方式写成这样的方式,

1
2
3
4
5
6
array=(
"A1 A2"
"B1 B2"
"C1 C2"
"D1 D2"
)

Reference

https://www.linuxjournal.com/content/bash-arrays