在bash函数中定义一个本地数组,并在该函数外部访问它

时间:2015-03-14 08:57:24

标签: arrays bash function

我正在尝试在bash函数中定义一个本地数组,并在该函数外部访问它。

我意识到BASH函数不返回值,但我可以将计算结果分配给全局值。我希望这段代码能够将array []的内容回显到屏幕上。我不确定为什么会失败。

function returnarray
{
local array=(foo doo coo)
#echo "inside ${array[@]}"
}


targetvalue=$(returnarray)
echo ${targetvalue[@]}

5 个答案:

答案 0 :(得分:8)

您有两种选择。第一个是@choroba规定的,它可能是最好和最简单的:不要在本地定义你的数组。

returnarray() {
    array=(foo doo coo) # NOT local
}

# call your function
returnarray
# now the array is in array and you may copy it for later use as follows:
targetvalue=( "${array[@]}" )
# print it to check:
declare -p targetvalue

这是整洁,简单,安全,完全避免使用子壳(因此它更有效)。但有一点需要注意:它不适用于稀疏数组(但这应该是一个小细节)。还有一个很小的缺点:需要复制数组。


另一种选择是将变量名称传递给函数,并让函数直接生成数组。这使用了namerefs,并且仅在Bash 4.3之后可用(但是如果可以的话,它真的很好用!):

generatearray() {
    # $1 is array name in which array is generated
    local -n array="$1" || return 1
    array=( foo doo coo )
}
# call function that constructs the array with the array name
generatearray targetvalue
# display it
declare -p targetvalue

答案 1 :(得分:2)

要使变量可从外部访问,请不要声明它local。让它全球化。

答案 2 :(得分:1)

首先,正如您所说,bash函数没有返回值。因此,传递本地值的唯一方法是echo它。

但是,如果将其解释为数组,这将导致您的targetvalue包含您在索引0中回显的所有内容。要告诉bash将零件视为数组零件,你必须用括号括起来 - 来自bash手册:

  

将数组分配给使用表单的复合赋值          name =(value1 ... valuen),其中每个值的形式为[sub-          脚本] =字符串。

#!/bin/bash

function returnarray
{
    local array=(foo doo coo)
    echo "${array[@]}"
}


targetvalue=($(returnarray))
echo ${targetvalue[@]}
echo ${targetvalue[1]}

然而,所有这些都是关于bash如何工作的编程。最好全局定义数组。

由于使用echo使bash解释了值,这只有在数组的值不受bash影响的情况下才有效,例如值可能不包含通配符或空格,通配符将扩展为匹配文件和值中的空格将转换为多个数组值。

答案 3 :(得分:0)

看看这个,可能是有空格和其他字符......

#!/bin/bash
function returnarray
{
newname=$1
local array=(foo doo coo)
declare -p array | sed "s/array/$newname/g"
}

eval $(returnarray glob)
echo elm0 ${glob[0]}
echo elm1 ${glob[1]}
echo elm2 ${glob[2]}

请参阅How to return an array in bash without using globals?

编辑:关于'数组'的评论是正确的......这是一个固定版本。 sed 用法我不介意......

#!/bin/bash
function returnarray
{
newname=$1
local array=(foo doo coo "declare -a array" aa)
declare -p array | sed "s/^declare -a array/declare -a $newname/"
}

eval $(returnarray glob)
echo elm0 ${glob[0]}
echo elm1 ${glob[1]}
echo elm2 ${glob[2]}
echo elm2 ${glob[3]}
echo elm2 ${glob[4]}

答案 4 :(得分:0)

您可以声明局部变量,然后printf一个逗号分隔值字符串,它可以很好地转换为数组。关键是使用printf而不是echo。

http://wiki.bash-hackers.org/commands/builtin/read

  

使用printf,因为(取决于设置),echo可能会解释一些baskslash-escapes或开关(如-n)。

代码:

- (void)setUp {
    [super setUp];
    // Put setup code here. This method is called before the invocation of each test method in the class.
    self.vcToTest = [[TableViewController alloc] init];

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    self.vcToTest = [storyboard instantiateViewControllerWithIdentifier:@"testTableView"];
    [self.vcToTest performSelectorOnMainThread:@selector(loadView) withObject:nil waitUntilDone:YES];
}

终端:

#Return csv of project.id's
function get_project() {
  local qry="select id from ${DB}.projects where identifier=\"${1}\";"
  local ids=`sudo -u ${DB_USER} ${DB_LOCATION} -u ${DB_USER} -p${DB_PASS} -s -e "${qry}"`
  #return
  while read -r element; do printf "%s," "$element"; done <<< "$ids"
}
#Return csv of member.id's
function get_members() {
  local qry="select user_id from ${DB}.members where project_id=${1};"
  local ids=`sudo -u ${DB_USER} ${DB_LOCATION} -u ${DB_USER} -p${DB_PASS} -s -e "${qry}"`
  #return
  while read -r element; do printf "%s," "$element"; done <<< "$ids"
}
projects=( $(get_project "newuser1") )
declare -p projects
member_ids=( $(get_members $projects) )
declare -p member_ids