我试图在 for 循环中检索一个值,但尽一切努力都失败了。在此脚本中,我必须声明 SSHFS 挂载脚本的远程路径。在下面的代码中,我将路径存储在 user[remote] 数组中。在脚本的更下方,该用户被保存在 $left 中。所以air[remote]将是$left[remote]。但是,我不知道该怎么做。我最近的努力${!left[remote]}
没有导致任何错误,只是导致空值。
如何使用 $left[remote] 动态获取远程路径值?
#!/bin/bash
declare -A air
air[remote]="/home/air"
declare -A bhm
bhm[remote]="/home/bhm"
declare -A schwimserver3
schwimserver3[remote]="/var/www/clients/client1/web7/home/schwimserver3"
#echo ${air[remote]}
for u in $HOME/Remote/SSHFS/*
do
if [ -d $u ]; then
basename "$u" >/dev/null
acct="$(basename -- $u)"
IFS=- read -r left right <<< "$acct"
if mountpoint "${HOME}/Remote/SSHFS/${acct}" >/dev/null; then
printf '%b\n' "unmount ${right},fusermount -u /home/schwim/Remote/SSHFS/${right}"
else
printf '%b\n' "mount ${right},sshfs -o workaround=rename $left@$right:${!left[remote]} /home/schwim/Remote/SSHFS/${acct}"
fi
fi
done
谢谢你的时间!
答案1
问题是,您需要双重解释该数组。如果 left="air",则 $left[remote] 不等于air[remote]
。
要执行双重替换,您需要首先解释$left
into air
,然后air[remote]
像这样解释:
$ air[remote]="/home/air" $ left="air" ; For clarity, lets make a temporary variable with the first substitution $ name_var='${'$left'[remote]}' ; Lets see the value of name_var $ echo $name_var ${air[remote]} ; Now, we need to force the shell to interpret this value $ eval echo $name_var /home/air ; Or, to store this in a value resolved_value=$( eval echo $name_var )
或者,作为单行:
resolved_value=$( eval echo '${'$left'[remote]}' )
这是如何工作的:
技巧在于创建 $name_var:
'${' (带单引号,而不是双引号)表示按原样使用字符(即不将它们解释为名为{
$left 的变量,然后将替换为它的变量) value "air"
'[remote]}' 将按原样使用这些字符(同样,单引号,而不是双引号),然后
命令eval
将这些字符(或变量 $name_var 的内容)替换到解释器中并处理其结果。那么就是变量 ${air[remote]}" 的值
在代码中,您可以构建 $resolved_value 变量并将其放入脚本中:
printf '%b\n' "mount ${right},sshfs -o workaround=rename $left@$right:${resolved_value} /home/schwim/Remote/SSHFS/${acct}"
或者插入整个表达式:
printf '%b\n' "mount ${right},sshfs -o workaround=rename $left@$right:$( eval echo '${'$left'[remote]}' ) /home/schwim/Remote/SSHFS/${acct}"
尽管第一个选项的可读性更好。
答案2
为什么不反转数组:
declare -A remotes=(
[air]="/home/air"
[bhm]="/home/bhm"
[imserver3]="/var/www/clients/client1/web7/home/schwimserver3"
)
那你就用"${remotes[$left]}"
.
这就是关联数组如此有用的原因:您不必使用动态变量名称。
要使用动态名称,请使用 bash 版本 4.3+ 并使用 namerefs:
declare -A foo=( [bar]=baz )
left=foo
declare -n ref=$left
echo "${ref[bar]}"
参考。3.4 外壳参数在手册中