编辑:

编辑:

经过一些 bash 自学和实验之后,我仍然无法从一个函数返回一个数组,而且我无论如何也看不到我的错误。

简而言之,应该/必须做的是使用一个函数,该函数从文件读取值/字符串,返回一个数组:

  • 声明一个数组:客户端
  • 将函数的返回数组分配给数组客户端
  • 显示阵列客户端

在我看来,该函数好像读取整个文件而不是逐行读取,从而将所有字符串放入数组中的单个单元格中,并且我不确定如何明确显示客户端[0],因为这个$(clients[0])在bash代码中失败

如果我做错了什么,也请指出这一点,或者提出任何优化建议

#!/bin/bash
readArray(){
        local array=()
        local i=0;
        local j=0
        while IFS= read -r LINE  && [[ -n "$LINE" ]] ; do 
                array[$((i++))]+=${LINE}; # Append line to the array
                ((j++))
        done < "$1";
        rtr=${array[@]}
}
string="/home/cybex/openvpntest/openvpn.log"
declare -a clients
#sed -i '/^$/d' $string
clients=$(readArray "$string")
echo "${clients[@]}"

echo -e "array not empty, displaying array contents\n"

for i in "${!clients[@]}"; do 
  echo "$i: ${clients[$i]}"
done
echo -e "\nfinished displaying contents of array"

猫openvpn.log

something
anotherthing
anotherlineoftext
here is one more line
and lastly
one with 
a few spaces
nice

更新 对于那些想看看我如何解决这个问题的人来说:

  • 声明一个“全局”数组

    declare -a clients
    
  • 当函数执行时,直接将值添加到客户端数组中

要显示数组的单个索引位置,请参考最后一行代码

echo "${clients[0]}"      or any other number >=0

工作代码:

declare -a clients
readArray(){
        local array=()
        local i=0;
        local j=0
        while IFS= read -r LINE  && [[ -n "$LINE" ]] ; do 
                clients[$((i++))]+=${LINE}; # Append line to the array
                ((j++))
        done < "$1";
}
string="/home/cybex/openvpntest/openvpn.log"
sed -i '/^$/d' $string
readArray "$string"
echo "${clients[@]}"

echo -e "array not empty, displaying array contents\n"

for i in "${!clients[@]}"; do 
  echo "$i: ${clients[$i]}"
done
echo -e "\nfinished displaying contents of array"
echo "${clients[0]}"

答案1

已经回答这里

您应该在谷歌中进行最少的搜索,因为这是“bash return array”返回的第一个链接

编辑:

在 bash 中,函数不返回值。它们可以返回状态(与其他程序相同)。

所以,如果你想返回某些东西,你应该使用在函数内部更新的全局变量。

答案2

讨论

如果您想要从函数返回一个数组,那么您可能知道您只能返回状态代码。嘘!您说。:-)

如果我们想在另一个函数/上下文中使用函数中的其他数据,该怎么办?

  1. 回声

假设 stdout 设置为终端,至少您可以看到变量或其他内容的内容。

  1. 输出重定向>或者>>

虽然不理想,但有可能。:-) 可能您还可以做更多的事情,但我们就此打住。

讨论继续...

假设我们认为上述选项 1 看起来很有希望。通常会发生什么?就像这样...

function listToString ()
{
    echo "$*"
}

参考:《UNIX:终极指南》,第二版,第 387 页(最后一段)

如果我调用doSomething,它可能会向 stdout 发送一个字符串消息。该输出可以用两种不同的方式捕获。

  1. 反引号`做某事`
  2. 这东西:$(做某事)

如果确实如此,那么您可以在另一个上下文中保存发送到标准输出的内容。

var1=`doSomething`

或者

var1=$(doSomething)

总之 ....

将列表转换为字符串。回显字符串。使用命令替换捕获回显的字符串(参见上文)。read结合使用这里是字符串( <<<) 将字符串转换为数组。随意使用数组。

文件:new_users

fsmith
jdoe

假设我们想使用我们创建的addAccounts循环遍历用户名参数的函数来添加新用户。执行顺序如下。

  1. 制作文件
  2. 读取文件
  3. 将列表转换为字符串
  4. 将字符串转换为数组。

代码如下

function listToString ()
{
    echo "$*"
}

usersString=$(listToString $(cat new_users))

read -a users <<< $usersString

addAccounts "${users[@]}"

listToString可能无法对所有输入行起作用。请对您的输入进行测试。

最后一行应该解析为:

addAccounts "fsmith" "jdoe"

很多人可能不理解这句话...

read -a users <<< $usersString

...因为他们从来没有听说过这里的字符串。

此解决方案不会从函数传递数组,但允许您将函数的输出转换为数组。有些人满足于将列表转换为字符串并称之为一天,但如果您真的想处理官方 bash 数组,上面的字符串将为您做到这一点。

答案3

这个技巧并不总是有效(当您的值带有空格,或者您想要返回依赖于输入值的值时),但它通常可以完成以下工作:

array_returning_func() {
    echo "cat dog tree"
}

declare -a arr="$(array_returning_func)"
for obj in ${arr[@]}; do
    echo "$obj"
done

相关内容