[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
"unset var" pops var off variable stack instead of unsetting it
From: |
Stephane Chazelas |
Subject: |
"unset var" pops var off variable stack instead of unsetting it |
Date: |
Fri, 17 Mar 2017 21:51:34 +0000 |
User-agent: |
Mutt/1.5.24 (2015-08-30) |
Hi,
consider this function:
split() (
unset -v IFS # default splitting
set -o noglob # disable glob
set -- $1 # split+(no)glob
[ "$#" -eq 0 ] || printf '<%s>\n' "$@"
)
Note the subshell above for the local scope for $IFS and for
the noglob option. That's a common idiom in POSIX shells when
you want to split something: subshell, set IFS, disable glob,
use the split+glob operator.
split 'foo * bar'
outputs
<foo>
<*>
<bar>
as expected. So far so good.
Now, if that "split" functions is called from within a function
that declares $IFS local like:
bar() {
local IFS=.
split $1
}
Then, the "unset", instead of unsetting IFS, actually pops a
layer off the stack.
For instance
foo() {
local IFS=:
bar $1
}
foo 'a b.c:d'
outputs
<a b>
instead of
<a>
<b>
because after the "unset IFS", $IFS is not unset (which would
result in the default splitting behaviour) but set to ":" as it
was before "bar" ran "local IFS=."
A simpler reproducer:
$ bash -c 'f()(unset a; echo "$a"); g(){ local a=1; f;}; a=0; g'
0
Or even with POSIX syntax:
$ bash -c 'f()(unset a; echo "$a"); a=0; a=1 eval f'
0
A work around is to change the "split" function to:
split() (
local IFS
unset -v IFS # default splitting
set -o noglob # disable glob
set -- $1 # split+(no)glob
[ "$#" -eq 0 ] || printf '<%s>\n' "$@"
)
For some reason, in that case (when "local" and "unset" are
called in the same function context), unset does unset the
variable.
Credits to Dan Douglas
(https://www.mail-archive.com/miros-mksh@mirbsd.org/msg00707.html)
for finding the bug. He did find a use for it though (get the
value of a variable from the caller's scope).
--
Stephane
- "unset var" pops var off variable stack instead of unsetting it,
Stephane Chazelas <=
- Re: "unset var" pops var off variable stack instead of unsetting it, Grisha Levit, 2017/03/17
- Re: "unset var" pops var off variable stack instead of unsetting it, Dan Douglas, 2017/03/17
- Re: "unset var" pops var off variable stack instead of unsetting it, Stephane Chazelas, 2017/03/17
- Re: "unset var" pops var off variable stack instead of unsetting it, Chet Ramey, 2017/03/18
- Re: "unset var" pops var off variable stack instead of unsetting it, Eric Blake, 2017/03/20
- Re: "unset var" pops var off variable stack instead of unsetting it, Chet Ramey, 2017/03/20
- Re: "unset var" pops var off variable stack instead of unsetting it, Stephane Chazelas, 2017/03/20
- Re: "unset var" pops var off variable stack instead of unsetting it, Chet Ramey, 2017/03/20