This question already has answers here:
Closed 4 years ago.
Shell script pass arguments with spaces
(2个答案)
我试图围绕bazaarvcb实用程序构建bash脚本,但是在构造参数时遇到了一些问题。
基本上,这是我想要执行的命令(简化版):
bazaarvcb backup -H 192.168.1.100 -u user -p password --roll-out 4 \
--exclude-disk "[Datastore1] MyVM - NAS/MyVM-NAS_1.vmdk" \
--exclude-disk "[Datastore2] MyVM - NAS/MyVM-NAS_2.vmdk" \
"MyVM - NAS" "/home/user/backup/MyVM - NAS/"

在命令行上执行上述操作或将其粘贴到一个简单的bash脚本中,一切都很好。但是,当我试图将排除磁盘(甚至VM名称)替换为脚本中的变量参数时,我会遇到问题。
例子:
#!/usr/bin/env bash

set -o xtrace

readonly __VM="MyVM - NAS"
readonly __BACKUPROOT="/home/user/backup/MyVM - NAS/"

readonly -a __EXCLUDE_DISKS=( \
'[Datastore1] MyVM - NAS/MyVM-NAS_1.vmdk' \
'[Datastore2] MyVM - NAS/MyVM-NAS_2.vmdk' )

disks_excluded=""
for (( i = 0 ; i < ${#__EXCLUDE_DISKS[@]} ; i++ )); do
    disks_excluded+="--exclude-disk \"${__EXCLUDE_DISKS[$i]}\" "
done

bazaarvcb backup -H 192.168.1.100 -u user -p password --roll-out 4 ${disks_excluded} "${__VM}" "${__BACKUPROOT}"

执行上述脚本时的结果是:
+ readonly '__VM=MyVM - NAS'
+ __VM='MyVM - NAS'
+ readonly '__BACKUPROOT=/home/user/backup/MyVM - NAS/'
+ __BACKUPROOT='/home/user/backup/MyVM - NAS/'
+ __EXCLUDE_DISKS=('[Datastore1] MyVM - NAS/MyVM-NAS_1.vmdk' '[Datastore2] MyVM - NAS/MyVM-NAS_2.vmdk')
+ readonly -a __EXCLUDE_DISKS
+ disks_excluded=
+ (( i = 0  ))
+ (( i < 2  ))
+ disks_excluded+='--exclude-disk "[Datastore1] MyVM - NAS/MyVM-NAS_1.vmdk" '
+ (( i++  ))
+ (( i < 2  ))
+ disks_excluded+='--exclude-disk "[Datastore2] MyVM - NAS/MyVM-NAS_2.vmdk" '
+ (( i++  ))
+ (( i < 2  ))
+ bazaarvcb backup -H 192.168.1.100 -u user -p password --roll-out 4 --exclude-disk '"[Datastore1]' MyVM - 'NAS/MyVM-NAS_1.vmdk"' --exclude-disk '"[Datastore2]' MyVM - 'NAS/MyVM-NAS_2.vmdk"' 'MyVM - NAS' '/home/user/backup/MyVM - NAS/'
usage: bazaarvcb [-h] [--version]  ...
bazaarvcb: error: unrecognized arguments: NAS/MyVM-NAS_1.vmdk" MyVM - NAS/MyVM-NAS_2.vmdk" MyVM - NAS /home/user/backup/MyVM - NAS/

任何帮助都将不胜感激。

最佳答案

shell在展开变量引用之前解析引号,因此将引号放入变量的值中没有任何用处——当它们被扩展到命令中时,对它们产生预期的效果已经太晚了。因此,当您使用:

...
disks_excluded+="--exclude-disk \"${__EXCLUDE_DISKS[$i]}\" "
...
bazaarvcb ... ${disks_excluded} ...

bazaarvcb获取传递的参数,如“--排除磁盘”、“数据存储1”、“MyVM”、““-”和“NAS/MyVM-NAS_1.vmdk”。双引号被视为参数的一部分,而不是参数周围的引号!幸运的是,解决方案很简单:将排除在外的磁盘存储为一个数组,就像对排除在外的磁盘所做的那样。注意,您还可以通过迭代数组元素而不是索引来简化for循环:
...
disks_excluded=() # Note that this declares disks_excluded as an empty array
for disk in "${__EXCLUDE_DISKS[@]}"; do
    disks_excluded+=("--exclude-disk" "${disk}")
done

bazaarvcb backup -H 192.168.1.100 -u user -p password --roll-out 4 "${disks_excluded[@]}" "${__VM}" "${__BACKUPROOT}"

注意${__EXCLUDE_DISKS[@]}${disks_excluded[@]}周围的双引号是必需的(正如[@]s一样)。

关于linux - bash脚本中的命令无法使用可变参数正确执行,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30419412/

10-11 22:37
查看更多