Shell – setting variables inside subshell when using <<

cshhere-documentshell-script

I am using the following method in order to pass commands into a subshell that is started by "newgrp".

#!/bin/csh
echo "Before newgrp"
/usr/bin/newgrp users <<EONG
echo "hello from within newgrp"
id
EONG
echo "After newgrp"

It works fine as long as I don't try and "set" anything in the subshell.

i.e

#!/bin/csh
echo "Before newgrp"
/usr/bin/newgrp users <<EONG
echo "hello from within newgrp"
set a=npy
echo $a
id
EONG
echo "After newgrp"

As you can see above, I set a=npy inside the subshell and doing an echo $a should return npy. However, I get to see an error as a is not declared.

Can someone tell me how I can set env vars inside a subshell while using <<

Best Answer

The << construct introduces a shell here document that is treated as if it were a double-quoted string as it is read, so variables expand immediately as they are read by the shell. You would see this clearly if you enable a shell feature that tells you about undefined variables. I'll use that feature in the BASH shell here:

$ set -o nounset
$ echo "$a"
bash: a: unbound variable
$ bash <<EOF
> a=foo
> echo "$a"
> EOF
bash: a: unbound variable

To stop the shell from expanding variables in the here document as it is being read, you can either single-quote the tag or backslash every use of every variable:

$ bash <<'EOF'
> a=foo
> echo "$a"
> EOF
foo

$ bash <<EOF
> a=foo
> echo "\$a"
> EOF
foo

Note that the types of quotes used around the variable inside the here document have nothing to do with whether or not the variable is expanded by the shell as the here document is being read.

p.s. Always double-quote your variable expansions so that they don't trigger unintended GLOB file name matches.

p.p.s. Turn on undefined-variable checking in you shells, to catch your typing errors. This would have clued you in to your problem.

p.p.p.s. Don't use C shells for scripting. They have many bugs and inconsistencies

Related Question