Piping output of one command into builtin "read" command
Piping output of one command into builtin "read" command
am 25.10.2007 23:58:20 von qazwart
I'm attempting to find out the revision of the Java JDK a user is
running. I first split the major and minor using "sed":
#Java is revision 1.4
java -version 2>&1 | sed -n '/^java version/s/^java version "\
([0-9][0-9]*\)\.\([0-9][0-9]*\).*$/\1 \2/p'
This prints out:
1 4
So far, so good. Now I want to read in the major and minor of the
revision into environment variables:
#Java is revision 1.4
$JAVA -version 2>&1 | sed -n '/^java version/s/^java version "\
([0-9][0-9]*\)\.\([0-9][0-9]*\).*$/\1 \2/p' \
| read major minor
echo "Major = $major Minor = $minor"
I now get this:
Major = Minor =
I thought the read command picks up STDIN, and I am sure I've done
stuff like this before. I've even tried this:
echo "this that" | read foo bar
echo "$foo bar"
But, that doesn't work either.
It's been a while since I've worked with shell scripts, but I could
have sworn that I've used "read" like this before since it really
works in splitting output into separate variables.
I know there are ways around this (I'm doing them), but I am really
interested in what I am doing wrong in with the "read" command.
Besides, this has to be able to run under pure Bourne shell, and not
BASH or Kornshell.
Any ideas?
Re: Piping output of one command into builtin "read" command
am 26.10.2007 00:08:48 von Stephane CHAZELAS
2007-10-25, 21:58(-00), David Weintraub:
> I'm attempting to find out the revision of the Java JDK a user is
> running. I first split the major and minor using "sed":
>
> #Java is revision 1.4
> java -version 2>&1 | sed -n '/^java version/s/^java version "\
> ([0-9][0-9]*\)\.\([0-9][0-9]*\).*$/\1 \2/p'
>
> This prints out:
>
> 1 4
>
> So far, so good. Now I want to read in the major and minor of the
> revision into environment variables:
environment variables are, like arguments, strings passed from
command to command. I thing you're confusing it with shell
variables.
>
> #Java is revision 1.4
> $JAVA -version 2>&1 | sed -n '/^java version/s/^java version "\
> ([0-9][0-9]*\)\.\([0-9][0-9]*\).*$/\1 \2/p' \
> | read major minor
> echo "Major = $major Minor = $minor"
>
> I now get this:
>
> Major = Minor =
>
> I thought the read command picks up STDIN, and I am sure I've done
> stuff like this before. I've even tried this:
Yes, but in
cmd1 | cmd2
you'll agree that as both commands run concurrently, they have
to be run in separate processes. So there's no guarantee that
the process running cmd2 will be the same as that of the the shell
interpreting your script. So "read major minor" may very well be
run in a subshell.
Try:
code=`
$JAVA -version 2>&1 | sed -n '
s/^java version \([0-9][0-9]*\)\.\([0-9][0-9]*\).*$/major=\1 minor=\2/p
'
`
eval "$code"
> It's been a while since I've worked with shell scripts, but I could
> have sworn that I've used "read" like this before since it really
> works in splitting output into separate variables.
>
> I know there are ways around this (I'm doing them), but I am really
> interested in what I am doing wrong in with the "read" command.
> Besides, this has to be able to run under pure Bourne shell, and not
> BASH or Kornshell.
[...]
bash and pdksh are known to run the rightmost part of a pipe in
a subshell.
But with the Bourne shell, it's even simpler: as soon as there's
a pipe or a redirection, there's a fork.
So even
read var < file
wouldn't work.
When you think of it, it's normal. Other shells have to resort
to dirty tricks in order to be able to call builtin commands
with file descriptors temporarily redirected to something else.
--
Stéphane
Re: Piping output of one command into builtin "read" command
am 28.10.2007 15:01:38 von gazelle
In article <1193349500.706682.256550@o38g2000hse.googlegroups.com>,
David Weintraub wrote:
>I'm attempting to find out the revision of the Java JDK a user is
>running. I first split the major and minor using "sed":
>
> #Java is revision 1.4
> java -version 2>&1 | sed -n '/^java version/s/^java version "\
>([0-9][0-9]*\)\.\([0-9][0-9]*\).*$/\1 \2/p'
>
>This prints out:
>
> 1 4
>
>So far, so good. Now I want to read in the major and minor of the
>revision into environment variables:
>
> #Java is revision 1.4
> $JAVA -version 2>&1 | sed -n '/^java version/s/^java version "\
>([0-9][0-9]*\)\.\([0-9][0-9]*\).*$/\1 \2/p' \
> | read major minor
> echo "Major = $major Minor = $minor"
>
>I now get this:
>
> Major = Minor =
This is an instance of "the subshell problem", a general problem with
Unix shells, that has several different manifestations.
My usual workaround for it in this instance is to use a "here document":
read major minor <
$(cmd)
X
Re: Piping output of one command into builtin "read" command
am 29.10.2007 09:12:41 von Konstantin Sologubov
Also you can use | (read MAJOR MINOR ; echo $MAJOR $MINOR)
On Sun, 28 Oct 2007 14:01:38 +0000 (UTC)
gazelle@xmission.xmission.com (Kenny McCormack) wrote:
> In article <1193349500.706682.256550@o38g2000hse.googlegroups.com>,
> David Weintraub wrote:
> >I'm attempting to find out the revision of the Java JDK a user is
> >running. I first split the major and minor using "sed":
> >
> > #Java is revision 1.4
> > java -version 2>&1 | sed -n '/^java version/s/^java version "\
> >([0-9][0-9]*\)\.\([0-9][0-9]*\).*$/\1 \2/p'
> >
> >This prints out:
> >
> > 1 4
> >
> >So far, so good. Now I want to read in the major and minor of the
> >revision into environment variables:
> >
> > #Java is revision 1.4
> > $JAVA -version 2>&1 | sed -n '/^java version/s/^java version "\
> >([0-9][0-9]*\)\.\([0-9][0-9]*\).*$/\1 \2/p' \
> > | read major minor
> > echo "Major = $major Minor = $minor"
> >
> >I now get this:
> >
> > Major = Minor =
>
> This is an instance of "the subshell problem", a general problem with
> Unix shells, that has several different manifestations.
>
> My usual workaround for it in this instance is to use a "here
> document":
>
> read major minor <
> $(cmd)
> X
>