如何从Bash中的脚本返回一个数组?

时间:2014-08-13 16:23:16

标签: arrays bash

假设我有一个名为“Hello'”的脚本。类似的东西:

array[0]="hello world"
array[1]="goodbye world"
echo ${array[*]}

我想在另一个脚本中做这样的事情:

tmp=(`Hello`)

我需要的结果是:

echo ${tmp[0]}  #prints "hello world"
echo ${tmp[1]}  #prints "goodbye world"

而不是

echo ${tmp[0]}  #prints "hello"
echo ${tmp[1]}  #prints "world"

或换句话说,每个单词都放在tmp数组中的不同位置。 我如何得到我需要的结果?

3 个答案:

答案 0 :(得分:6)

将其作为NUL分隔的流发送:

printf '%s\0' "${array[@]}"

......而在另一方面,请从该流中读取:

array=()
while IFS= read -r -d '' entry; do
  array+=( "$entry" )
done

这通常与过程替换一起派上用场;在下面的示例中,初始代码位于以generate_an_array调用的命令(无论是函数还是外部进程)中:

array=()
while IFS= read -r -d '' entry; do
  array+=( "$entry" )
done < <(generate_an_array)

您还可以使用declare -p发出一个字符串eval来获取内容:

array=( "hello world" "goodbye world" )
declare -p array

......而另一方面......

eval "$(generate_an_array)"

然而,这不太可取 - 它不像bash那样可以移植到编程语言(而几乎所有语言都可以读取NUL分隔的流),并且它要求接收程序信任发送程序返回declare -p结果而非恶意内容。

答案 1 :(得分:2)

虽然有解决方法,但你不能真正从bash函数或脚本“返回”一个数组,因为“返回”一个值的正常方法是将它作为字符串发送到stdout并让调用者通过命令替换捕获它。 [注1]对于简单的字符串或非常简单的数组(例如数字数组,其中元素不能包含空格),这很好,但它实际上不是发送结构化数据的好方法。

有一些解决方法,例如打印带有特定分隔符(特别是NUL字节)的字符串,可以由调用者解析,或者以可执行bash语句的形式打印,调用者可以使用{{{ 1}},但总的来说,最简单的机制是要求调用者提供可以放置值的数组变量的名称。这仅适用于bash函数,因为脚本不能修改调用者的环境,并且它只适用于父进程中直接调用的函数,因此它不适用于管道。实际上,这是一种类似于eval内置函数和其他一些read内置函数的机制。

这是一个简单的例子。函数bash有三个参数:数组名称,分隔符和字符串:

split

例如:

split ()  { 
  IFS=$2 read -a "$1" -r -d '' < <(printf %s "$3")
}

备注:

  1. 任何函数或脚本都有状态返回,这是一个小整数;这是$ # Some text $ lorem="Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt" # Split at the commas, putting the pieces in the array phrase $ split phrase "," "$lorem" # Print the pieces in a way that you can see the elements. $ printf -- "--%s\n" "${phrase[@]}" --Lorem ipsum dolor sit amet -- consectetur adipisicing elit -- sed do eiusmod tempor incididunt return特殊表单实际返回的内容。但是,状态返回主要用作布尔值,当然不能携带结构化值。

答案 2 :(得分:1)

hello.sh

declare -a array       # declares a global array variable
array=(
    "hello world"
    "goodbye world"
)

other.sh

. hello.sh
tmp=( "${array[@]}" )  # if you need to make a copy of the array
echo "${tmp[0]}"
echo "${tmp[1]}"

如果您真的希望函数吐出脚本将捕获的值,请执行以下操作:

hello.sh

#!/bin/bash
array=(
    "hello world"
    "goodbye world"
)
printf "%s\n" "${array[@]}"

other.sh

#!/bin/bash
./hello.sh | {
    readarray -t tmp
    echo "${tmp[0]}"
    echo "${tmp[1]}"
}

# or
readarray -t tmp < <(./hello.sh)        
echo "${tmp[0]}"
echo "${tmp[1]}"