Reputation: 1932
I have a c application that calls out to a csh script with lots of information. I'd like to expand that in such a way that the csh script can loop through the environment variables. For example, the c application would set the following envs
COUNT=4
SOMETHING_1=HELLO
SOMETHING_2=WORLD
SOMETHING_3=WIDE
SOMETHING_4=WEB
And the csh script can loop through the SOMETHINGs and print out the envs based on the count env.
Is it possible to evaluate a programatically generated env?
I tried doing this to test the theory:
#!/bin/csh -f
foreach n ( 1 2 3 4 )
eval "$SOMETHING"_"$n"
end
But that obviously didn't work.
Upvotes: 1
Views: 1993
Reputation: 37298
All you're missing is a \
char, i.e.
#!/bin/csh -f
foreach n ( 1 2 3 4 )
eval echo \$"SOMETHING"_"$n"
# --------^--- here
end
I've added an echo
here so that eval
has something safe, but visible to do.
Change your shebang line to use debug/trace mode, i.e.
#!/bin/csh -fvx
and define
SOMETHING=abc
and you'll see the two passes that the eval
does, you'll (should) see
where
echo $SOMETHING_1
echo "value of abc_1 =$abc_1 XXX"
but of course, you'll have to define a value for variable abc_1.
Finally, don't get to rely on using eval. Use it only as a last resort, and only where you have control over what strings will be eval
ed.
It would be very easy for a malcontent to pass in harmful code that will be executed by the eval
.
(And sorry, I don't have a csh
handy to test this so let me know if you have troubles).
Finally, read widely published articles that csh
is not a great language for programming. Switch to bash
or ksh
at your earliest convenience. You won't regret it.
IHTH
Upvotes: 3
Reputation: 263547
If one of the variables is not set, your script will crash; referring to an undefined variable in csh/tcsh is an error. (This is unlike sh/bash, where $FOO
by default expands to the empty string if the variable isn't set.)
If you can safely assume that all the relevant variables are set, then shellter's solution should be ok. If you want to do some error checking, read on.
The csh/tcsh syntax for testing whether a variable $VAR
is defined or not is $?VAR
. It evaluates to 0
or 1
.
An example:
#!/bin/tcsh -f
setenv SOMETHING_1 foo
setenv SOMETHING_3 bar
foreach i (1 2 3 4 5)
set is_set = `eval echo '$?SOMETHING_'$i`
if ($is_set) then
echo '$SOMETHING_'$i is set to `eval echo '$SOMETHING_'$i`
else
echo '$SOMETHING_'$i is not set
endif
end
Output:
$SOMETHING_1 is set to foo
$SOMETHING_2 is not set
$SOMETHING_3 is set to bar
$SOMETHING_4 is not set
$SOMETHING_5 is not set
As shellter's answer mentions, eval
is potentially unsafe unless you have complete control over what's passed to it. In this particular case that's not an issue.
Another possible solution might be to parse the output of printenv
-- but that could run into problems if some environment variables have values with strange characters such as newlines.
Or you could write and invoke a small program in another language; for example C's getenv()
or Perl's %ENV
don't require the use of eval
to determine whether an arbitrary environment variable is set or not, and are not vulnerable to values with strange characters.
I vaguely recall that in some old versions of csh, the $?VAR
syntax worked only for shell variables, not for environment variables. It does work in tcsh and in more modern versions of csh.
Upvotes: 3