我编写了一个脚本,我希望用户输入一个目录或许多目录,并检查每个目录对于此讨论不重要的内容。所有内部目录也会被检查到指定的深度。
虽然我可以声明要启动的数组Directories0
(输入目录),但我无法以任何方式引用它...结果:错误的替换。显然,Directories1
将是深度= 1,Directories2
是深度= 2,依此类推......
以下是一段代码:
let Recurse=4 ## say... variable value ##
[ "$Recurse" ] && let MaxDepth="$Recurse" || let MaxDepth=0
declare -i depth=0
IFS=$'\n'
## declare -a Directories${depth}=("${@}") ## <—— doesn't work
## declare -a Directories${depth}="("${@}")" ## <—— works if the brackets only are quoted...
## declare -a Directories${depth}=\("${@}"\) ## <—— ... or escaped
declare -a "Directories${depth}=("${@}")"
IFS=$' \t\n'
## Nested loop, depth counter increases for each directory depth. I want to stop at a specific depth which is entered as an option ##
for (( depth = 0; depth <= MaxDepth; depth++ )); do ## MaxDepth is entered as option ##
until [ -z "${Directories${depth}[*]}" ]; do ## ***** bad substitution error ***** ##
declare input="$(follow "${Directories${depth}[0]}")" ## follow is a script that resolves symlinks and Finder aliases ##
CheckDirectory "${input%/}/" ## check directory ##
case $? in
## Tests passed ##
0) if [[ "$Recurse" && "$depth" -lt "$MaxDepth" ]]; then
IFS=$'\n'
## get ready to check sub-directories ##
declare -a Directories$(( depth + 1 ))="("${Directories$(( depth + 1 ))[@]}" $(find -P "${Directories${depth}[0]}" -type d -mindepth 1 -maxdepth 1 -exec follow '{}' \;))"
IFS=$' \t\n'
fi
true;;
## Tests failed ##
*) false;;
esac
[ $? -eq 0 ] && unset Directories${depth}[0] || exit 1 ## if test fails, exit, if succeeds, move on to next directory ##
declare -a Directories${depth}="("${Directories${depth}[@]}")" ## re-shuffle the array to get rid of null value at index 0 ##
(( element++ ))
done
done
下面是一个简化版本,如果你不想通过上面的代码,这就是问题的症结所在:
depth=2
declare -a "Directories${depth}=(yo man ma me mo)"
echo "${Directories${depth}[4]}"
> -bash: ${Directories${depth}[4]}: bad substitution
echo "${Directories2[4]}"
> mo
解决方案,任何人?
- Aesthir
答案 0 :(得分:4)
您需要${}
构造内的文字变量名称。如果要引用其名称在运行时确定的变量,则需要明确地通过间接级别。
name="Directories${depth}[4]"
echo ${!name}
这对作业没有帮助。只要您在当前范围内(而不是在包含范围内)进行分配,就可以使用内置typeset
进行计算分配。但是要小心:bash有一个启发式方法,可以将类似数组赋值语法的赋值转换为数组赋值。这意味着如果元素将存储绝对文件名(始终以/
开头),则下面的代码是可以的,但如果它将存储任意文件名(可能类似于{{ 1}})。
(foo)
或者,可以使用typeset "Directories${depth}[4]=new value"
对任何shell运行时确定其名称的变量进行赋值。这有利于在任何shell中工作,而不仅仅是bash。但是你需要非常小心:很难得到正确的报价。最好让eval
的论点做得尽可能少。使用临时变量来获取存储值。
eval
答案 1 :(得分:1)
使用eval,这有效:
eval echo \${Directories${depth}[4]}
mo
答案 2 :(得分:0)
试试eval
#!/bin/bash depth=2 declare -a "Directories${depth}=(yo man ma me mo)" eval echo "\${Directories${depth}[4]}" echo "${Directories2[4]}"
答案 3 :(得分:0)
你快到了那里:
declare -a Directories${depth}="( yo man ma me mo )"
工作(没有eval,顺便说一句)。要访问该值,请使用$ {!}语法:
temp=Directories$depth[@]
echo ${!temp}
答案 4 :(得分:0)
也许这是一个(迟来的)回答问题的答案? (问题并不像提问者所认为的那样清楚,我觉得......)
#!/bin/bash
for depth in {0..5}
do
var_value=(yo man ma me mo "last value")
var_name="directories${depth}"
eval "${var_name}=\"${var_value[${depth}]}\""
value="directories${depth}"
printf "directories{$depth} = ${!value}"
[ $depth -eq 0 ] && printf " \t directories0=$directories0\n"
[ $depth -eq 1 ] && printf " \t directories1=$directories1\n"
[ $depth -eq 2 ] && printf " \t directories2=$directories2\n"
[ $depth -eq 3 ] && printf " \t directories3=$directories3\n"
[ $depth -eq 4 ] && printf " \t directories4=$directories4\n"
[ $depth -eq 5 ] && printf " \t directories5=$directories5\n"
done
产生:
directories{0} = yo directories0=yo
directories{1} = man directories1=man
directories{2} = ma directories2=ma
directories{3} = me directories3=me
directories{4} = mo directories4=mo
directories{5} = last value directories5=last value
重点是,如果变量名由另一个变量组成,那么如何为其赋值。例如,如果设置“foobar = value”是将变量设置为值的常规方法,那么如果x = foo和y = bar,如何设置“$ {x} $ {y} = value”=&gt ; e.g:
foobar=test
echo $foobar
> test
x=foo
y=bar
eval "export ${x}${y}=\"value\""
echo $foobar
> value
如果我误解了这个问题,那么,我并不是非常惊讶: - )