4

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 <<

2
  • You'll probably need to escape $a as \$a to prevent it from being substituted by the shell before being passed as stdin to newgrp.
    – ninjalj
    Commented Oct 14, 2013 at 13:23
  • 1
    @ninjalj - please write that up as an answer so that it can be accepted and this issue can get marked as resolved.
    – slm
    Commented Oct 14, 2013 at 14:49

2 Answers 2

3

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

1

You are using a here-document delimited by the EONG string.

When introducing here-documents with <<word, whether or not the here-document is subject to expansion depends on whether any character in word is quoted. When no character is quoted, the here-document is subject to parameter expansion, command substitution, and arithmethic expansion. When at least one character is quoted, the here-document is not subject to expansion; Bourne and Korn (and POSIX) shells use a totally unquoted word as final delimiter, while C shells use word as is.

You could rewrite your example as:

#!/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"

Otherwise, with an unquoted word, you need to escape $a as \$a to prevent it from being substituted by the shell before being passed as stdin to newgrp:

#!/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"

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.