经过一些 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
讨论
如果您想要从函数返回一个数组,那么您可能知道您只能返回状态代码。嘘!您说。:-)
如果我们想在另一个函数/上下文中使用函数中的其他数据,该怎么办?
- 回声
假设 stdout 设置为终端,至少您可以看到变量或其他内容的内容。
- 输出重定向:>或者>>
虽然不理想,但有可能。:-) 可能您还可以做更多的事情,但我们就此打住。
讨论继续...
假设我们认为上述选项 1 看起来很有希望。通常会发生什么?就像这样...
function listToString ()
{
echo "$*"
}
参考:《UNIX:终极指南》,第二版,第 387 页(最后一段)。
如果我调用doSomething
,它可能会向 stdout 发送一个字符串消息。该输出可以用两种不同的方式捕获。
- 反引号`做某事`
- 这东西:$(做某事)
如果确实如此,那么您可以在另一个上下文中保存发送到标准输出的内容。
var1=`doSomething`
或者
var1=$(doSomething)
总之 ....
将列表转换为字符串。回显字符串。使用命令替换捕获回显的字符串(参见上文)。read
结合使用这里是字符串( <<<
) 将字符串转换为数组。随意使用数组。
文件:new_users
fsmith
jdoe
假设我们想使用我们创建的addAccounts
循环遍历用户名参数的函数来添加新用户。执行顺序如下。
- 制作文件
- 读取文件
- 将列表转换为字符串
- 将字符串转换为数组。
代码如下
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