From owner-freebsd-questions Tue Feb 13 22:26:30 1996 Return-Path: owner-questions Received: (from root@localhost) by freefall.freebsd.org (8.7.3/8.7.3) id WAA15302 for questions-outgoing; Tue, 13 Feb 1996 22:26:30 -0800 (PST) Received: from mramirez.sy.yale.edu (mramirez.sy.yale.edu [130.132.57.207]) by freefall.freebsd.org (8.7.3/8.7.3) with SMTP id WAA15297 for ; Tue, 13 Feb 1996 22:26:26 -0800 (PST) Received: (from mrami@localhost) by mramirez.sy.yale.edu (8.6.12/8.6.9) id BAA26070; Wed, 14 Feb 1996 01:25:57 -0500 Date: Wed, 14 Feb 1996 01:25:57 -0500 (EST) From: Marc Ramirez Reply-To: mrami@minerva.cis.yale.edu To: Archie Cobbs cc: freebsd-questions@freebsd.org Subject: Re: stupid sh tricks In-Reply-To: <199602132231.OAA10024@bubba.tribe.com> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-questions@freebsd.org Precedence: bulk On Tue, 13 Feb 1996, Archie Cobbs wrote: > > Hi, > > This is a pretty basic sh(1) question. I apologize that it's not > FreeBSD specific... but I couldn't seem to find the answer in the > man page or ftp://rtfm.mit.edu/pub/usenet-by-hierarchy/comp/unix/shell. > Also, I don't get news right now... ok, enough apologies... > > Consider the following script: > > #!/bin/sh > > foo () > { > GLOBAL_ONE="foo_one" > GLOBAL_TWO="foo_two" > while read ARG; do > GLOBAL_TWO=${ARG} > done > return 0 > } > > bar () > { > GLOBAL_ONE="bar_one" > GLOBAL_TWO="bar_two" > } > > echo before : GLOBAL_ONE=${GLOBAL_ONE} and GLOBAL_TWO=${GLOBAL_TWO} > > echo "value" | foo > echo foo set: GLOBAL_ONE=${GLOBAL_ONE} and GLOBAL_TWO=${GLOBAL_TWO} > > bar > echo bar set: GLOBAL_ONE=${GLOBAL_ONE} and GLOBAL_TWO=${GLOBAL_TWO} > > The output of this script is: > > before : GLOBAL_ONE= and GLOBAL_TWO= > foo set: GLOBAL_ONE= and GLOBAL_TWO= > bar set: GLOBAL_ONE=bar_one and GLOBAL_TWO=bar_two > > Why!? Seems like have a "read" in the function foo() changes > variable scoping or something. This "read" seems to be a very > broken command... another example: > > $ cat foo > foo-contents > $ read VAR < foo > $ echo $VAR > foo-contents > $ VAR= > $ echo $VAR > > $ cat foo | read VAR > $ echo $VAR > > $ exit > > So "read" seems to "know" whether its input is coming from a > file or a pipe. Is this a bug or a feature? :-) Feature. sh handles pipes by forking. The read statement is being run in a child process, the child exits, and then the value is lost. I don't know how you would propagate that info backwards... You could get around it using fifos, or you could do something like var="`cat foo`" if at all possible. Maybe some fancy trickery with eval. Marc. -- If a President doesn't do it to his wife, he'll do it to his country.