Subject: Re: bug in sh?
To: None <current-users@NetBSD.ORG>
From: Christos Zoulas <christos@deshaw.com>
List: current-users
Date: 05/25/1995 15:01:58
In article <9505251347.AA06187@alfred.ons.octel.com> jonb@alfred.ons.octel.com (Jon Buller) writes:
>Could someone tell me if this is proper behavior for sh, a known bug,
>or a newly discovered critter?  the shell was suped just a few days ago,
>rebuilt and installed.  Anyway, here is what happened:

This is proper behavior. Although this is one of the mis-features of
the shell I hate the most, since there aren't any official rules that
specify under what conditions a subshell gets forked...

>jonb@bullbox[4]% cat data
>key1 k1data1 k1data2 k1data3
>key2 k2data1 k2data2 k2data3
>jonb@bullbox[5]% cat prog1
>#!/bin/sh -
>
>grep "^$1" ./data | read key data1 data2 data3
>echo $key - $data1 - $data2 - $data3
>
>exit 0
>jonb@bullbox[6]% ./prog1 key1
>- - -
>jonb@bullbox[7]% cat prog2
>#!/bin/sh -
>
>grep "^$1" ./data | while read key data1 data2 data3
>do
>   echo $key - $data1 - $data2 - $data3
>done
>
>exit 0
>jonb@bullbox[8]% ./prog2 key1
>key1 - k1data1 - k1data2 - k1data3
>jonb@bullbox[9]% 
>
>
>Notice that the read command does not appear to want to do anything
>unless it has a loop to work in.  I went through my POSIX.2 spec,
>and nothing jumped out at me WRT the read command doing something
>like this.  Any suggestions?

Well, the problem is not with the read command. When you pipe the read
command directly, a subshell is forked for the read builtin; the
variables get set in the subshell, but after the subshell exits these
values are lost. In prog2, the echo's are happening inside the loop
of the while subshell... Prog's 1a and 2a will make this more obvious:

[10:59am] 224>cat prog1a
#!/bin/sh -

grep "^$1" ./data |
        (read key data1 data2 data3; echo $key - $data1 - $data2 - $data3)

exit 0
[10:59am] 225>./prog1a
key1 - k1data1 - k1data2 - k1data3
[10:59am] 226>cat prog2a
#!/bin/sh -

grep "^$1" ./data | while read key data1 data2 data3
do
   echo $key - $data1 - $data2 - $data3
done
echo $key - $data1 - $data2 - $data3

exit 0
[10:59am] 227>./prog2a
key1 - k1data1 - k1data2 - k1data3
key2 - k2data1 - k2data2 - k2data3
- - -

christos