Is there a less laborious way for setting a local version of the $path
array than what's shown in the following snippet?
foo () {
local holdpath
holdpath=($path)
local path
path=($holdpath)
if ( some_condition ) path=( $PREFIX $path )
# do stuff
}
I'm referring specifically to the song-and-dance with holdpath
…
If instead I define
foo () {
local path=($path)
if ( some_condition ) path=( $PREFIX $path )
# do stuff
}
…the first assignment to path
triggers a bad pattern
error. Of course, if instead I define
foo () {
local path
path=($path)
if ( some_condition ) path=( $PREFIX $path )
# do stuff
}
…the first assignment to path
makes no difference (i.e. it can be omitted without altering the results); with or without it, $path
will be empty.
EDIT:
The following script tests the various suggestions I've gotten so far:
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
}
The output is:
# foo_0
22
22
# foo_1
22
1
# foo_2
22
22
So the outputs for foo_0
and foo_2
are at least consistent with what I'm trying to achieve. Something is not working with foo_1
as given above, but I get rid of the (q)
in the assignment to path
, i.e.
foo_1 () {
echo ${#path}
eval "local path; path=($path)"
echo ${#path}
}
…then the output agrees with that of foo_0
and foo_2
. Unfortunately, even after reading the documentation for the q
qualifier a couple of times, I don't quite understand what it's supposed to be doing in the original recipe.
Also, I cannot understand why the following command-line variant of foo_0
differs from the one above:
% (foo_0a () { echo ${#path}; local PATH=$PATH; echo ${#path} }; foo_0a)
22
1
FWIW, the corresponding command-line variants of foo_1
and foo_2
produce the same results as their originals in the script:
% (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
Also, in all the cases above in which echo ${#path}
produces 1
instead of 22
the reason is that the local $path
variable contains all the individual paths in a single string, separated by spaces.
Best Answer
While for tied arrays, you can use rici's answer, in the general case, you could do:
The
(q)
is to quote the elements of the arrays. For instance, for a value of$PATH
like/foo bar:/x$y
,"${(q)path[@]}"
would expand to/foo\ bar /x\$y
. We need to escape those space and dollar characters because that string is passed toeval
.You could also do:
which would work with any type of variable, but that forks an extra process.