views:

686

answers:

5

May God never give you the bane of working on Solaris. Now, I am trying to run this simple shell script:

#!/bin/sh

input="a
b
c"
data="123"

while read eachline
do      
   data="$data$eachline"
done <<  EOF
$(echo "$input")
EOF

echo "$data"
exit 0

On RHEL(BASH) I receive output as expected i.e "123abc", however, on Solaris I receive just "123".

After fair bit of googling, I realized that Solaris is forking a process for code inside the while loop and hence the variable's($data) value is not reflected on the outside of while loop.

Any hope to make this code compatible on both platforms would be greatly appreciated.

And oh yes, using a temp file for redirection would not be a very elegant solution :| .

+2  A: 

Do you have a bash executable on the Solaris box ? I note you're referring to bash on RHEL, but your shell is set to #!/bin/sh (i.e. the vanilla Bourne shell).

Brian Agnew
I did "which sh" on respective OSs and accordingly changed to "#!/usr/bin/sh" and "#!/bin/sh" on Solaris and RHEL. However, there was no change in the result. :(
pavanlimo
But do you have a /bin/bash on your Solaris box? I *think* but I'm not sure, that /bin/sh on Linux is bash (you can check this via sh --version). So you would want to run /bin/bash on Solaris
Brian Agnew
I would like to use the default shell of an OS which would be in /bin/sh. On Solaris, this points to CSH and on RHEL this points to BASH. I would not want to hard code.
pavanlimo
I would really hope /bin/sh doesn't point to /bin/csh, as they're completely different shells with completely different syntax
Brian Agnew
A: 

Your script works fine on Mac OS X 10.5, which is certified Single Unix Specification version 3.

The behaviour of while in /bin/sh on Solaris is very strange. Can you provide the link where you found the forking issue?

A possible solution may be to use another shell, e.g., /bin/ksh.


Edit

The examples provided by your links don't show an issue with while but a normal behaviour of any shell. The basic construct of all of them is:

first_command | second_command_updating_variable

The fact that second_command_updating_variable is a while loop is not important. What is important is that the second command of the pipe is executed in a subshell and cannot modify variables of its parent shell.

mouviciel
Unfortunately, I would not want to hard code to any shell.http://www.craig-russell.co.uk/bash-variable-scope-in-while-loop/ http://edwardawebb.com/linux/scope-issue-bash-loops http://nion.modprobe.de/blog/archives/531-Altering-a-variable-outside-the-scope-of-a-loop-influenced-by-a-subshell.html
pavanlimo
A: 

How about this (please note backticks):

#!/bin/sh

input="a
b
c"
data="123"

z=`while read eachline
do      
   data="$data$eachline"
done <<  EOF
$(echo "$input")
EOF
echo $data
`
echo $z
exit 0
anon
Nope, doesn't work :( , since $data is echoed outside the loop. I am still getting "123" as the output.
pavanlimo
A: 

This code below solved my problem. I guess the key here was to echo the variable from within the subshell and ofcourse, not use the "here" document.

I have tested this code on CSH/BASH/KSH.

#!/bin/sh
input="a
b
c"

printf "$input" | { 
data="123"
while read eachline
do      
    data="$data$eachline"
done 
echo "$data"
}

exit 0

My heartfelt thanks to all who participated in this discussion.

pavanlimo
A: 

Why execute a subshell in the here document?

while read eachline
do      
   data="$data$eachline"
done <<  EOF
$(echo "$input")
EOF

You could just interpolate:

while read eachline
do      
   data="$data$eachline"
done <<  EOF
$input
EOF

Or echo:

echo "$input" | while read eachline
do      
   data="$data$eachline"
done

Actually, when I tested these, they all worked on Solaris just fine for me, so I'm not sure why you had trouble.

Brian Campbell