2017-03-06 101 views
0

我试图了解我在这里做错了什么,但似乎无法确定原因。我想从输出中为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 

的阵列将有像这样的数据中的每个:

[[email protected]/]$ arr107=($(onedatastore show 107 | sed 's/[A-Z]://' | cut -f2 -d\:)) 
[[email protected]/]$ 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\:)' 

我似乎无法找出对这种情况下使用的语法。

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

希望有人能帮忙。感谢

+0

哪些具体版本? –

+1

请务必阅读[Bash FAQ 001](http://mywiki.wooledge.org/BashFAQ/001)。 – chepner

回答

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

现在,这可能容易出现安全漏洞,因为它会对内部命令替换的输出进行双重评估。在*'eval'被调用之后,该命令替换应该被转义为仅运行*,而不是*之前*。 –

+0

顺便说一句,如果你的目标是bash 4.3,使用namevars访问'arr $ i'很容易。同样的写作,就此而言。 –

+0

使用'declare'而不是'eval'也是一个好主意。 – chepner

0

readarraymapfile,在bash 4.0加入,将直接读入的数组:

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}') 

或者,可以在bash 4.3使用namevars创建别名数组与任意命名阵列:庆典的

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}') 
+0

我也喜欢这个答案。唯一的问题是试图获得输出,因为我需要比较每个阵列中的字段,以确定哪个数据存储最少使用。我会+1这只是因为你提供了bash 3.x及更低版本的机制,即使它没有被问到,我在我的问题中也不明确。 – user1782878