Bash脚本 - 从函数返回数组

时间:2021-08-11 23:20:28

I am making a bash script and I have encountered a problem. So let's say I got this

我正在制作一个bash脚本,我遇到了一个问题。所以,假设我得到了这个

function create_some_array(){
  for i in 0 1 2 3 .. 10
  do
    a[i]=$i
  done
}

create_some_array
echo ${a[*]}

Is there any way I can make this work? I have searched quite a lot and nothing I found worked. I think making the a[] a global variable should work but I can't find something that actually works in my code. Is there any way to return the array from the function to main program?

我有什么方法可以做这个工作吗?我搜索了很多,没有找到任何工作。我认为使a []成为一个全局变量应该可以工作,但我找不到在我的代码中实际工作的东西。有没有办法将数组从函数返回到主程序?

Thanks in advance

提前致谢

3 个解决方案

#1


3  

This works fine as described. The most likely reason it doesn't work in your actual code is because you happen to run it in a subshell:

这描述得很好。它在您的实际代码中不起作用的最可能原因是因为您碰巧在子shell中运行它:

cat textfile | create_some_array
echo ${a[*]}

would not work, because each element in a pipeline runs in a subshell, and

不起作用,因为管道中的每个元素都在子shell中运行,并且

myvalue=$(create_some_array)
echo ${a[*]}

would not work, since command expansion happens in a subshell.

不起作用,因为命令扩展发生在子shell中。

#2


2  

You can make an array local to a function, and then return it:

您可以为函数创建一个本地数组,然后返回它:

function create_some_array(){
    local -a a=()
    for i in $(seq $1 $2); do
        a[i]=$i
    done
    echo ${a[@]}
}

declare -a a=()

a=$(create_some_array 0 10)

for i in ${a[@]}; do
   echo "i = " $i
done

#3


2  

This won't work as expected when there are whitespaces in the arrays:

当数组中有空格时,这将无法正常工作:

function create_some_array() {
    local -a a=()
    for i in $(seq $1 $2); do
        a[i]="$i $[$i*$i]"
    done
    echo ${a[@]}
}

and worse: if you try to get array indices from the outside "a", it turns out to be a scalar:

更糟糕的是:如果你试图从外部“a”获得数组索引,那么它就是一个标量:

echo ${!a[@]}

even assignment as an array wont help, as possible quoting is naturally removed by the echo line and evaluation order cannot be manipulated to escape quoting: try

即使作为一个数组赋值也不会有帮助,因为回声线自然会删除引用,并且无法操纵评估顺序以逃避引用:尝试

function create_some_array() {
...
    echo "${a[@]}"
}

a=($(create_some_array 0 10))
echo ${!a[@]}

Still, printf seems not to help either:

尽管如此,printf似乎也没有帮助:

function create_some_array() {
...
    printf " \"%s\"" "${a[@]}"
}

seems to produce correct output on one hand:

似乎一方面产生正确的输出:

$ create_some_array 0 3; echo
 "0 0" "1 1" "2 4" "3 9"

but assignment doesn't work on the other:

但是赋值不适用于另一个:

$ b=($(create_some_array 0 3))
$ echo ${!b[@]}
0 1 2 3 4 5 6 7

So my last trick was to do assignment as follows:

所以我的最后一招是做如下任务:

$ eval b=("$(create_some_array 0 3)")
$ echo -e "${!b[@]}\n${b[3]}"
0 1 2 3
3 9

Tataaa!

P.S.: printf "%q " "${a[@]}" also works fine...

P.S。:printf“%q”“$ {a [@]}”也可以正常工作......

#1


3  

This works fine as described. The most likely reason it doesn't work in your actual code is because you happen to run it in a subshell:

这描述得很好。它在您的实际代码中不起作用的最可能原因是因为您碰巧在子shell中运行它:

cat textfile | create_some_array
echo ${a[*]}

would not work, because each element in a pipeline runs in a subshell, and

不起作用,因为管道中的每个元素都在子shell中运行,并且

myvalue=$(create_some_array)
echo ${a[*]}

would not work, since command expansion happens in a subshell.

不起作用,因为命令扩展发生在子shell中。

#2


2  

You can make an array local to a function, and then return it:

您可以为函数创建一个本地数组,然后返回它:

function create_some_array(){
    local -a a=()
    for i in $(seq $1 $2); do
        a[i]=$i
    done
    echo ${a[@]}
}

declare -a a=()

a=$(create_some_array 0 10)

for i in ${a[@]}; do
   echo "i = " $i
done

#3


2  

This won't work as expected when there are whitespaces in the arrays:

当数组中有空格时,这将无法正常工作:

function create_some_array() {
    local -a a=()
    for i in $(seq $1 $2); do
        a[i]="$i $[$i*$i]"
    done
    echo ${a[@]}
}

and worse: if you try to get array indices from the outside "a", it turns out to be a scalar:

更糟糕的是:如果你试图从外部“a”获得数组索引,那么它就是一个标量:

echo ${!a[@]}

even assignment as an array wont help, as possible quoting is naturally removed by the echo line and evaluation order cannot be manipulated to escape quoting: try

即使作为一个数组赋值也不会有帮助,因为回声线自然会删除引用,并且无法操纵评估顺序以逃避引用:尝试

function create_some_array() {
...
    echo "${a[@]}"
}

a=($(create_some_array 0 10))
echo ${!a[@]}

Still, printf seems not to help either:

尽管如此,printf似乎也没有帮助:

function create_some_array() {
...
    printf " \"%s\"" "${a[@]}"
}

seems to produce correct output on one hand:

似乎一方面产生正确的输出:

$ create_some_array 0 3; echo
 "0 0" "1 1" "2 4" "3 9"

but assignment doesn't work on the other:

但是赋值不适用于另一个:

$ b=($(create_some_array 0 3))
$ echo ${!b[@]}
0 1 2 3 4 5 6 7

So my last trick was to do assignment as follows:

所以我的最后一招是做如下任务:

$ eval b=("$(create_some_array 0 3)")
$ echo -e "${!b[@]}\n${b[3]}"
0 1 2 3
3 9

Tataaa!

P.S.: printf "%q " "${a[@]}" also works fine...

P.S。:printf“%q”“$ {a [@]}”也可以正常工作......