Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

variables set on command line

13 views
Skip to first unread message

Sam Steingold

unread,
Aug 24, 2011, 11:24:38 AM8/24/11
to bug-...@gnu.org
CYGWIN_NT-5.2-WOW64 sds 1.7.9(0.237/5/3) 2011-03-29 10:10 i686 Cygwin
BASH_VERSION='4.1.10(4)-release'

at the bash prompt I observe this:
$ f(){ echo a=$a b=$b c=$c ; }
$ unset a b c
$ a=a b=b f
a=a b=b c=
$ f
a= b= c=
which I believe is correct (i.e., variables set in "a=a b=b f" are unset
after f terminates).

alas, when I call /bin/sh on the same machine, I see this:

f(){ echo a=$a b=$b c=$c ; }
f
a= b= c=
a=a b=b f
a=a b=b c=
f
a=a b=b c=
exit

i.e., variables set in "a=a b=b f" survive to the next command.
$ /bin/sh --version
GNU bash, version 4.1.10(4)-release (i686-pc-cygwin)

is this the expected behavior?

thanks.

--
Sam Steingold (http://sds.podval.org/) on CentOS release 5.6 (Final) X 11.0.60900031
http://palestinefacts.org http://openvotingconsortium.org http://memri.org
http://www.PetitionOnline.com/tap12009/ http://dhimmi.com
He who laughs last thinks slowest.


Eric Blake

unread,
Aug 24, 2011, 11:31:45 AM8/24/11
to bug-...@gnu.org
On 08/24/2011 09:24 AM, Sam Steingold wrote:
> CYGWIN_NT-5.2-WOW64 sds 1.7.9(0.237/5/3) 2011-03-29 10:10 i686 Cygwin
> BASH_VERSION='4.1.10(4)-release'
>
> at the bash prompt I observe this:
> $ f(){ echo a=$a b=$b c=$c ; }
> $ unset a b c
> $ a=a b=b f
> a=a b=b c=
> $ f
> a= b= c=
> which I believe is correct (i.e., variables set in "a=a b=b f" are unset
> after f terminates).

This is bash's default behavior, but it violates POSIX.

>
> alas, when I call /bin/sh on the same machine, I see this:

That tells bash to strictly obey POSIX, so you get the POSIX behavior.

>
> f(){ echo a=$a b=$b c=$c ; }
> f
> a= b= c=
> a=a b=b f
> a=a b=b c=
> f
> a=a b=b c=

Which is indeed correct under the rules for POSIX (basically, POSIX
requires function calls to behave like special built-ins, such that
changes to the environment persist after the function call - the bash
developer thinks the posix rule is counterintuitive, which is why the
default bash behavior is opposite the posix behavior).

Your question is not cygwin-specific.

> is this the expected behavior?

Yes.

--
Eric Blake ebl...@redhat.com +1-801-349-2682
Libvirt virtualization library http://libvirt.org

Sam Steingold

unread,
Aug 24, 2011, 12:07:14 PM8/24/11
to bug-...@gnu.org
> * Eric Blake <roy...@erqung.pbz> [2011-08-24 09:31:45 -0600]:

>> f(){ echo a=$a b=$b c=$c ; }
>> f
>> a= b= c=
>> a=a b=b f
>> a=a b=b c=
>> f
>> a=a b=b c=
>
> Which is indeed correct under the rules for POSIX

This sucks big time.
So if I want to bind a variable for an eval invocation and do this:

eval "`./libtool --tag=CC --config | grep '^archive_cmds='`"
CC='${CC}' libobjs='$libs' deplibs='${CLFLAGS}' compiler_flags='${CFLAGS}' \
soname='$dll' lib='$lib' output_objdir='$dyndir' \
eval XCC_CREATESHARED=\"${archive_cmds}\"

and I want CC to have an old value after the second eval, I need to save
it and restore it by hand, like this:

CC_save=$CC
CC='${CC}' libobjs='$libs' deplibs='${CLFLAGS}' compiler_flags='${CFLAGS}' \
soname='$dll' lib='$lib' output_objdir='$dyndir' \
eval XCC_CREATESHARED=\"${archive_cmds}\"
CC=$CC_save

however, this does not distinguish between unset CC and CC=''.
(is there a way to distinguish these two situations?)

thanks!

--
Sam Steingold (http://sds.podval.org/) on CentOS release 5.6 (Final) X 11.0.60900031

http://ffii.org http://palestinefacts.org http://honestreporting.com
http://thereligionofpeace.com http://openvotingconsortium.org http://dhimmi.com
Abandon all hope, all ye who press Enter.


Eric Blake

unread,
Aug 24, 2011, 12:19:06 PM8/24/11
to bug-...@gnu.org
On 08/24/2011 10:07 AM, Sam Steingold wrote:
>> * Eric Blake<roy...@erqung.pbz> [2011-08-24 09:31:45 -0600]:
>>> f(){ echo a=$a b=$b c=$c ; }
>>> f
>>> a= b= c=
>>> a=a b=b f
>>> a=a b=b c=
>>> f
>>> a=a b=b c=
>>
>> Which is indeed correct under the rules for POSIX
>
> This sucks big time.

Such is life when dealing with shell portability.

> So if I want to bind a variable for an eval invocation and do this:
>
> eval "`./libtool --tag=CC --config | grep '^archive_cmds='`"
> CC='${CC}' libobjs='$libs' deplibs='${CLFLAGS}' compiler_flags='${CFLAGS}' \
> soname='$dll' lib='$lib' output_objdir='$dyndir' \
> eval XCC_CREATESHARED=\"${archive_cmds}\"
>
> and I want CC to have an old value after the second eval, I need to save
> it and restore it by hand, like this:
>
> CC_save=$CC
> CC='${CC}' libobjs='$libs' deplibs='${CLFLAGS}' compiler_flags='${CFLAGS}' \
> soname='$dll' lib='$lib' output_objdir='$dyndir' \
> eval XCC_CREATESHARED=\"${archive_cmds}\"
> CC=$CC_save
>
> however, this does not distinguish between unset CC and CC=''.
> (is there a way to distinguish these two situations?)

Yes - autoconf does this all the time, using an idiom roughly like this:

CC_set=${CC+set}
CC_save=$CC
do stuff that modifies $CC
if test "$CC_set" = set; then
CC=$CC_save
else
unset CC
fi

Also, you can use command to suppress the ability of built-ins like eval
(but not function calls) to affect the current environment:

$ unset foo
$ foo=bar eval :
$ echo $foo
bar
$ unset foo
$ foo=bar command eval :
$ echo $foo
$

0 new messages