从for循环输出创建数组

时间:2017-03-06 21:20:02

标签: arrays bash loops for-loop

我试图理解我在这里做错了什么,但似乎无法确定原因。我想从bash中的for循环输出创建一组数组。以下是我到目前为止的代码:

for i in `onedatastore list | grep pure02 | awk '{print $1}'`; 
do 
     arr${i}=($(onedatastore show ${i} | sed 's/[A-Z]://' | cut -f2 -d\:)) ; 
     echo "Output of arr${i}: ${arr${i}[@]}" ; 
done

条件的输出如下:

107
108
109

我想要做的是基于这些唯一ID是创建数组:

arr107
arr108
arr109

数组中每个都有这样的数据:

[oneadmin@opennebula/]$ arr107=($(onedatastore show 107 | sed 's/[A-Z]://' | cut -f2 -d\:))
[oneadmin@opennebula/]$ echo ${arr107[@]}
DATASTORE 107 INFORMATION 107 pure02_vm_datastore_1 oneadmin oneadmin 0 IMAGE vcenter vcenter /var/lib/one//datastores/107 FILE READY DATASTORE CAPACITY 60T 21.9T 38.1T - PERMISSIONS um- u-- --- DATASTORE TEMPLATE CLONE_TARGET="NONE" DISK_TYPE="FILE" DS_MAD="vcenter" LN_TARGET="NONE" RESTRICTED_DIRS="/" SAFE_DIRS="/var/tmp" TM_MAD="vcenter" VCENTER_CLUSTER="CLUSTER01" IMAGES

当我在脚本部分尝试这个时,虽然我得到了输出错误:

./test.sh: line 6: syntax error near unexpected token `$(onedatastore show ${i} | sed 's/[A-Z]://' | cut -f2 -d\:)'

我似乎无法弄清楚在这种情况下使用的语法。

最后我想要做的是能够比较不同的数据存储区,并根据哪些数据存储区有更多的可用空间,将虚拟机部署到它。

希望有人可以提供帮助。感谢

2 个答案:

答案 0 :(得分:0)

您可以使用eval(可能不安全)和declare(更安全)命令:

for i in $(onedatastore list | grep pure02 | awk '{print $1}'); 
do 
    declare "arr$i=($(onedatastore show ${i} | sed 's/[A-Z]://' | cut -f2 -d\:))"
    eval echo 'Output of arr$i: ${arr'"$i"'[@]}'
done

答案 1 :(得分:0)

在bash 4.0中添加的

readarraymapfile将直接读入数组:

while IFS= read -r i <&3; do
  readarray -t "arr$i" < <(onedatastore show "$i" | sed 's/[A-Z]://' | cut -f2 -d:)
done 3< <(onedatastore list | awk '/pure02/ {print $1}')

更好的是,通过bash 3.x,可以使用read -a来读取数组:

shopt -s pipefail # cause pipelines to fail if any element does

while IFS= read -r i <&3; do
  IFS=$'\n' read -r -d '' -a "arr$i" \
    < <(onedatastore show "$i" | sed 's/[A-Z]://' | cut -f2 -d: && printf '\0')
done 3< <(onedatastore list | awk '/pure02/ {print $1}')

或者,可以使用namevars为bash 4.3中具有任意命名数组的数组创建别名:

while IFS= read -r i <&3; do
  declare -a "arr$i"
  declare -n arr="arr$i"
  # this is buggy: expands globs, string-splits on all characters in IFS, etc
  # ...but, well, it's what the OP is asking for...
  arr=( $(onedatastore show "$i" | sed 's/[A-Z]://' | cut -f2 -d:) )
done 3< <(onedatastore list | awk '/pure02/ {print $1}')
相关问题