有没有$path
比以下代码片段中显示的更省力的方法来设置数组的本地版本?
foo () {
local holdpath
holdpath=($path)
local path
path=($holdpath)
if ( some_condition ) path=( $PREFIX $path )
# do stuff
}
我特指的是歌舞表演holdpath
……
如果我定义
foo () {
local path=($path)
if ( some_condition ) path=( $PREFIX $path )
# do stuff
}
...第一个赋值会path
触发bad pattern
错误。当然,如果我定义
foo () {
local path
path=($path)
if ( some_condition ) path=( $PREFIX $path )
# do stuff
}
...第一个赋值path
没有什么区别(即可以省略而不改变结果);有或没有它,$path
都将是空的。
编辑:
以下脚本测试了我迄今为止收到的各种建议:
foo_0 () {
echo ${#path}
local PATH=$PATH
echo ${#path}
}
foo_1 () {
echo ${#path}
eval "local path; path=(${(q)path})"
echo ${#path}
}
foo_2 () {
echo ${#path}
eval "$(local -p path)"
echo ${#path}
}
for i ( 0 1 2 ) {
fn=foo_$i
echo "# $fn"
$fn
echo
}
输出是:
# foo_0
22
22
# foo_1
22
1
# foo_2
22
22
foo_0
因此和的输出foo_2
至少与我想要实现的目标一致。正如上面给出的那样,有些东西不起作用,但我在分配给 时foo_1
去掉了,即(q)
path
foo_1 () {
echo ${#path}
eval "local path; path=($path)"
echo ${#path}
}
foo_0
...那么输出与和 的输出一致foo_2
。不幸的是,即使阅读了q
几次限定符的文档,我也不太明白它在原始配方中应该做什么。
另外,我无法理解为什么以下命令行变体foo_0
与上面的不同:
% (foo_0a () { echo ${#path}; local PATH=$PATH; echo ${#path} }; foo_0a)
22
1
FWIW,相应的命令行变体foo_1
和foo_2
产生与脚本中原始结果相同的结果:
% (foo_1a () { echo ${#path}; eval "local path; path=(${(q)path})"; echo ${#path} }; foo_1a)
22
1
% (foo_2a () { echo ${#path}; eval "$(local -p path)"; echo ${#path}; }; foo_2a)
22
22
此外,在上述所有情况下,echo ${#path}
产生1
而不是22
原因是局部$path
变量包含单个字符串中的所有单独路径,并用空格分隔。
答案1
使用标量PATH
形式而不是数组path
。使其中任何一个有效地本地化都使它们都本地化,因此:
foo() {
local PATH=$PATH
if ( some_condition ) path=( $PREFIX $path )
# do stuff
}
(请注意,如果某些路径组件嵌入了 ,则这将不起作用:
。)
遗憾的是,无法在一条语句中初始化局部数组参数,因此无法使用其原始值来初始化局部数组参数。
答案2
而对于捆绑数组,你可以使用里奇的回答,一般情况下,你可以这样做:
foo() {
eval "local array; array=(${(q)array[@]})"
...
}
这(q)
是引用数组的元素。例如,对于$PATH
like的值/foo bar:/x$y
,"${(q)path[@]}"
将扩展为/foo\ bar /x\$y
。我们需要转义这些空格和美元字符,因为该字符串被传递给eval
.
你还可以这样做:
foo() {
eval "$(local -p array)"
...
}
它适用于任何类型的变量,但这会产生一个额外的过程。