From owner-freebsd-questions@FreeBSD.ORG Thu May 8 20:55:08 2014 Return-Path: Delivered-To: freebsd-questions@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id D96268FE for ; Thu, 8 May 2014 20:55:08 +0000 (UTC) Received: from mx02.qsc.de (mx02.qsc.de [213.148.130.14]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 9C52F282 for ; Thu, 8 May 2014 20:55:08 +0000 (UTC) Received: from r56.edvax.de (port-92-195-108-40.dynamic.qsc.de [92.195.108.40]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx02.qsc.de (Postfix) with ESMTPS id E3FC927729; Thu, 8 May 2014 22:54:59 +0200 (CEST) Received: from r56.edvax.de (localhost [127.0.0.1]) by r56.edvax.de (8.14.5/8.14.5) with SMTP id s48Ksxil007319; Thu, 8 May 2014 22:54:59 +0200 (CEST) (envelope-from freebsd@edvax.de) Date: Thu, 8 May 2014 22:54:59 +0200 From: Polytropon To: Rick Miller Subject: Re: Bourne variable unset outside while() Message-Id: <20140508225459.83f70b3c.freebsd@edvax.de> In-Reply-To: References: Reply-To: Polytropon Organization: EDVAX X-Mailer: Sylpheed 3.1.1 (GTK+ 2.24.5; i386-portbld-freebsd8.2) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Cc: FreeBSD Questions X-BeenThere: freebsd-questions@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: User questions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 08 May 2014 20:55:08 -0000 On Thu, 8 May 2014 14:48:22 -0400, Rick Miller wrote: > Hi all, > > I have a Bourne shell script that echoes the contents of a data structure > to a while() loop that iterates over the data and is expected to append a > string from the current iteration to a different list. Inside the while(), > it works fine, but echo'ing the list outside the loop produces empty > output. I expect the variable to maintain it's final state after > processing the while(), but it does not appear to be doing so. > > /** The script **/ > > #! /bin/sh -x > > fs="freebsd-ufs gprootfs 1G > freebsd-swap gpswapfs 1G > freebsd-ufs gpvarfs 1G"; > > echo "${fs}" | > while read -r fstype fslabel fssize; do > > labels="${labels} ${fslabel}"; > echo "${labels}"; > > done > > echo -e "\nlabels = ${labels}"; > > /** End the script **/ > > The output from this script is at http://pastebin.com/mxNLLWtm > > This almost appears to be an issue with scope, but I've not encountered > this before, especially in such simple context. I must be missing > something obvious and just looking for feedback to send me off in the right > direction. You have identified the problem: With the | redirector, a subshell is started which populates ${labels}, but at the "higher" level ${labels} keeps its setting (in this case, implicit empty string). Here's a workaround, using awk: #!/bin/sh fs="freebsd-ufs gprootfs 1G freebsd-swap gpswapfs 1G freebsd-ufs gpvarfs 1G" labels=`echo "${fs}" | awk '{printf("%s ", $2);}'` echo "labels = ${labels}" In this example, with `...`, which is the same as $(...), also starts a subshell, but assigns its output to a variable, so there will be no scope problem. This idea uses the advantage that your delimiter is newline, and awk can process the input line per line, printing "incomplete lines" (no newline added) as output. The result will be: labels = gprootfs gpswapfs gpvarfs Is this what you expected? -- Polytropon Magdeburg, Germany Happy FreeBSD user since 4.0 Andra moi ennepe, Mousa, ...