[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Stupid shell script question about "read"



On Thu, Mar 02, 2006 at 09:19:02AM -0800, David Kirchner wrote:
> On 3/2/06, Kevin B. McCarty <kmccarty@princeton.edu> wrote:
> > Hi list,
> >
> > Could someone tell me why the following works in zsh but not in
> > bash/posh/dash?
> >
> > benjo[3]:~% echo foo bar baz | read a b c
> > benjo[4]:~% echo $a $b $c
> > foo bar baz
> >
> > If I try the same with bash (or other sh-compatible shells), the
> > variables $a $b and $c are unset.  From the bash man page:
> > ...
> > So "read" claims to read from the standard input, but it doesn't
> > actually seem to happen when a pipe is involved.
> 
> What's happening here is that the pipe is causing a subshell to be
> spawned, which is then parsing the command "read a b c".

> 
> http://linuxgazette.net/issue57/tag/1.html
> 
> The example he gives, with the < <() syntax, worked in bash, but not
> in Debian or FreeBSD's /bin/sh.

In more recent bashes, the following should work as well

#!/bin/bash
read a b c <<<`echo foo bar baz`
echo $a $b $c

The <<< ("here strings") are an extension of the "here document" syntax,
IOW, the string given after <<< is supplied as stdin to the command.

Then, there's another variant, which is about as ugly as it can get...
It should, however, work with most bourne shell compatible shells:

#!/bin/sh
eval `echo foo bar baz | (read a b c; echo "a='$a';b='$b';c='$c'" )`
echo $a $b $c

To get the variable's values from the subshell back to the main shell,
a shell code fragment is written on stdout, captured with backticks,
and then eval'ed in the main shell...  (this is the moment when I
usually switch to some other scripting language -- if not before :)

Cheers,
Almut



Reply to: