The command
export FOO
should, according to my understanding, create an environment variable FOO
(with a blank value) even if this variable did not exist previously and no value was supplied. This position seems to be supported by the zsh
manual. See the following from man zshbuiltins
:
export [ name[=value] ... ]
The specified names are marked for automatic export to the environment of subsequently executed commands. Equivalent
to typeset -gx. If a parameter specified does not already exist, it is created in the global scope.
However, when I use C's getenv
function, this environment variable is not registered. here is a simple example. Consider the following program:
% cat foo.c
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
const char* foo = getenv("FOO");
if ( foo == NULL ) {
printf("The environment variable 'FOO' does not exist!\n");
} else {
printf("%s\n", foo);
return 0;
}
}
Compile it:
% gcc --version
gcc (GCC) 7.2.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
% gcc foo.c -o foo
Consider the following three executions:
% ./foo
The environment variable 'FOO' does not exist!
% export FOO
% ./foo
The environment variable 'FOO' does not exist!
% export FOO=BAR
% ./foo
BAR
What is wrong in the middle case? Shouldn't it display a blank line?
Note that you didn't need to write your own program to display the env vars. The env
command already exists:-)
This is a quirk that dates back at least four decades to the earliest UNIX shells. Modern shells (including bash, zsh, and ksh) all exhibit that quirk. The quirk is that if you export VAR
and VAR
has not already been assigned a value it is marked to be exported but will not actually be in the exported environment until you assign it a value. You can see this for yourself using any of those shells; not just zsh:
$ export FOO
$ env | grep FOO
$ FOO=''
$ env | grep FOO
FOO=
$ FOO=bar
$ env | grep FOO
FOO=bar
$ BAR=''
$ export BAR
$ env | grep BAR
BAR=
That last example hints at why export
behaves this way.
There is some bug here. First, let's change the program to use the environment variables directly, avoiding the possibility of a bug in getenv
:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[], char *arge[])
{
for (char **p = arge; *p; ++p)
if (0 == strncmp(*p, "FOO", 3))
{
puts(*p);
return 0;
}
}
Now, if we build this and execute it in a fresh zsh
, we get no output, as expected.
If we export FOO
and execute it, we again get no output, but export | grep FOO
export | grep FOO
shows FOO=''
. So zsh
did define it, to be an empty string, but zsh failed to pass it to the program (or something in the environment-variable handling in the exec
routines messed up).
However, start a fresh zsh
, execute export FOO
twice, and then the program. Now the output is FOO=
. But export | grep FOO
export | grep FOO
still shows FOO=''
. So there seems to be some hidden state in zsh
: Sometimes it does not export defined variables.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.