具有数组输入和输出的 Bash 函数

Jos*_*ick 0 arrays bash shell function

如果我在 bash shell 中定义一个数组:

a=()
a+=("A")
a+=("B")
a+=("C")
Run Code Online (Sandbox Code Playgroud)

我可以按预期与它交互:

echo "${a[0]}"
# Returns "A"

echo "${a[1]}"
# Returns "B"
Run Code Online (Sandbox Code Playgroud)

但是当我通过函数运行同一个数组时,我一定做错了什么。首先,我将定义我的函数:

function sort_array {
  declare -a array=("${!1}")
  local sorted=()

  sorted+=("1")
  sorted+=("2")
  sorted+=("3")

  echo "${sorted[@]}"
}
Run Code Online (Sandbox Code Playgroud)

现在让我们调用它并检查结果:

b=()
b=$(sort_array a[@])
echo "${b[0]}"

# Returns "1 2 3"
# But I'm expecting b[0] == 1
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?我意识到我的示例可以完全删除函数参数,但我的最终目标是编写一个 bashsort_array()函数,我可以向其传递数组并获取数组。

che*_*ner 5

bash没有数组。该语句echo "${sorted[@]}"不会“返回”数组值,它只是将数组的每个元素写入标准输出,并用单个空格分隔。(更具体地说,数组扩展产生一系列单词,每个元素一个,然后作为参数传递echo。)

模拟起来有点困难bash。您必须创建一个全局数组参数,这是在 4.2 之前无法在函数内执行的操作bash。在 4.3 中引入 nameref 之前,使用该数组很困难bash

sort_array () {
    declare -n input=$1     # Local reference to input array
    declare -ga "$2"        # Create the output array
    declare -n output="$2"  # Local reference to output array

    # As a simple example, just reverse the array instead
    # of sorting it.
    n=${#input[@]}
    for((i=n-1; i>=0; i--)); do
        echo "*** ${input[i]}"
        output+=( "${input[i]}" )
    done
}
Run Code Online (Sandbox Code Playgroud)

现在,您传递sort_array两个参数,分别是输入和输出数组的名称。

$ a=("foo 1" "bar 2" "baz 3")
$ sort_array a b
$ echo "${b[0]}"
baz 3
Run Code Online (Sandbox Code Playgroud)