views:

40

answers:

4

I want to set an environment variable in bash, which starts from a digit. The environment of the process can contain such variables (it just doesn't care). But in the shell you have to create the variables, and then export them so they go to the environment. Is there a way to put some value into shell's environment without touching variables, or maybe create a variable that starts with a digit?

+2  A: 

The only valid beginning character types for bash variables are letters and underscores.

msbmsb
It is true for variables. But process'es environment just doesn't care. Now way to put it there without bash variable restrictions?
valeryz
@valeryz: you'd have to manipulate the environment in a C program, and use `execve()` to relay it to bash. It is not convenient or sensible. You can also create multiple entries for a single variable that way - that isn't convenient or sensible either.
Jonathan Leffler
A: 

Why do you want to do this? You can do:

export _1="some value"

or

export a1="some value"

The reason that you can't do what you're asking is that a variable like "$1" would be confused with the positional parameter $1.

Dennis Williamson
Because I do this in Cygwin for WinDDK 'build' utility, which wants a '386' variable. I understand the reasons it doesn't work as you descrive.
valeryz
+3  A: 

The only way I could think of was by starting a new shell using env:

env 0FOO=BAR /usr/bin/bash

I tried this under Cygwin and it seemed to work.

Bert F
That's nice, thanks! I found I could upgrade to bash 4.1, but your approach should work anywhere, an extra bash process is fine for me.
valeryz
Clever; I wonder if that's a bug or a feature in `env`.
Jonathan Leffler
As @valeryz points out, there isn't the same restrictions on the identifiers in process environment block (IAFAIK - if someone has seen some, please comment) as there are in bash variables. Since env doesn't violate bash's rules for bash variables (it bypasses them altogether), this usage would seem kosher to me.
Bert F
+1 And you can do `exec env 0FOO=BAR /usr/bin/bash` to replace the current shell.
Dennis Williamson
A: 

The processing required is fiddly and tedious and not dreadfully sensible, but (in outline, error checks on malloc() omitted):

char **env = environ;
while (*env != 0)
    *env++;
char **newenv = malloc((env - environ + 1) * sizeof(*newenv));
memcpy(newenv, environ, (env - environ) * sizeof(char *));
newenv[env - environ] = "386=pygmalion";
newenv[env - environ + 1] = 0;
char *args[] = { "modded-env-bash", 0 };
execve("/bin/bash", args, newenv);
exit(1);
Jonathan Leffler
why wouldn't putenv() or setenv() work?
valeryz
This requires custom programming (though clearly the name and value of the env var could be collected from the command line), and isn't as neat as using the `env` program that Bert F suggested.
Jonathan Leffler
@valeryz: They might - they might not. There's a decent chance `putenv()` will work, but it might check what you supply; there's a decent chance `setenv()` won't work because it takes name and value separately and might validate the name (though POSIX only says that '=' signs are not allowed; everything else seems to be fair game). OK, rewrite the code to use `setenv()`...have fun. Better to use `env` command if that works where you need it to.
Jonathan Leffler
agree about the command, just was curious about the code above.
valeryz