|
|
|
|
||||||
| comp.unix.shell Using and programming the Unix shell. |
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#1 |
|
Messages: n/a
Hébergeur: |
For some reason, I am not able to access variables that were changed in a
while loop, after the while loop finishes. For example: i=0 echo "this is a test" | while read line do i = `expr $i + 1` done echo $i ------------------------------- The echo statement prints 0 rather than 1. Does anyone know why? |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
"Doug Ritschel" <ritschel@optonline.net> writes:
> i=0 > echo "this is a test" | while read line; do > i = `expr $i + 1` > done > echo $i The while loop is run in a subshell and it has it's own local variables so changing them won't change the value of oryginal variable. In fact AFAIK the question was answered in FAQ. -- Best regards, _ _ .o. | Liege of Serenly Enlightened Majesty of o' \,=./ `o ..o | Computer Science, Michal "mina86" Nazarewicz (o o) ooo +--<mina86*tlen.pl>--<jid:mina86*jabber.org>--ooO--(_)--Ooo-- |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
"Michal Nazarewicz" <mina86@tlen.pl> wrote in message news:87r6z3d27r.fsf@erwin.piotrekn... > "Doug Ritschel" <ritschel@optonline.net> writes: > > > i=0 > > echo "this is a test" | while read line; do > > i = `expr $i + 1` > > done > > echo $i > > The while loop is run in a subshell and it has it's own local > variables so changing them won't change the value of oryginal > variable. > > In fact AFAIK the question was answered in FAQ. > > Why, then , if I run the following, the echo prints 3, which is the number of lines in the hosts file. i=0 while read line; do i = `expr $i + 1` done < /etc/hosts echo $i |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
"Doug Ritschel" <ritschel@optonline.net> wrote in message news:8sZHg.206$Y43.108@newsfe09.lga... > > "Michal Nazarewicz" <mina86@tlen.pl> wrote in message > news:87r6z3d27r.fsf@erwin.piotrekn... > > "Doug Ritschel" <ritschel@optonline.net> writes: > > > > > i=0 > > > echo "this is a test" | while read line; do > > > i = `expr $i + 1` > > > done > > > echo $i > > > > The while loop is run in a subshell and it has it's own local > > variables so changing them won't change the value of oryginal > > variable. > > > > In fact AFAIK the question was answered in FAQ. > > > > > > Why, then , if I run the following, the echo prints 3, which is the number > of lines in the hosts file. > > i=0 > while read line; do > i = `expr $i + 1` > done < /etc/hosts > echo $i > > Found the below answer: The disadvantage of the pipe-to-while method is that each element in the pipeline is run in a subshell, so variables set inside the while loop (for example) won't be set after the loop is complete[*]. find . | { while read line do : whatever word=${line%% *} done : variables set within the loop are still available here, e.g.: printf "%s\n" "$word" } |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
"Doug Ritschel" <ritschel@optonline.net> writes:
> "Michal Nazarewicz" <mina86@tlen.pl> wrote in message > news:87r6z3d27r.fsf@erwin.piotrekn... >> "Doug Ritschel" <ritschel@optonline.net> writes: >> >> > i=0 >> > echo "this is a test" | while read line; do >> > i = `expr $i + 1` >> > done >> > echo $i >> >> The while loop is run in a subshell and it has it's own local >> variables so changing them won't change the value of oryginal >> variable. > > Why, then , if I run the following, the echo prints 3, which is the > number of lines in the hosts file. > > i=0 > while read line; do i=`expr $i + 1`; done < /etc/hosts > echo $i Because there is no need for subshell. In the first while loop you've used a pipe so shell had to run another process. In the second while loop you didn't use a pipe but only redirect stdout to be read from /etc/hosts. -- Best regards, _ _ .o. | Liege of Serenly Enlightened Majesty of o' \,=./ `o ..o | Computer Science, Michal "mina86" Nazarewicz (o o) ooo +--<mina86*tlen.pl>--<jid:mina86*jabber.org>--ooO--(_)--Ooo-- |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
On 2006-08-26, Doug Ritschel wrote:
> > "Michal Nazarewicz" <mina86@tlen.pl> wrote in message > news:87r6z3d27r.fsf@erwin.piotrekn... >> "Doug Ritschel" <ritschel@optonline.net> writes: >> >> > i=0 >> > echo "this is a test" | while read line; do >> > i = `expr $i + 1` >> > done >> > echo $i >> >> The while loop is run in a subshell and it has it's own local >> variables so changing them won't change the value of oryginal >> variable. >> >> In fact AFAIK the question was answered in FAQ. >> >> > > Why, then , if I run the following, the echo prints 3, which is the number > of lines in the hosts file. > > i=0 > while read line; do > i = `expr $i + 1` > done < /etc/hosts > echo $i First, you did not get any output from that script unless you have an executable named 'i'. You are asking the shell to execute a command named 'i', with arguments of '=' and '1'; you are not incrementing a variable. You meant: i=`expr $i + 1` (no spaces around the equals sign). Second, you were not running it (with the error fixed) in a Bourne shell. If you were, you would still have seen '0'. In a Bourne shell, the redirecion alone is enough to force a subshell. -- Chris F.A. Johnson, author <http://cfaj.freeshell.org> Shell Scripting Recipes: A Problem-Solution Approach (2005, Apress) ===== My code in this post, if any, assumes the POSIX locale ===== and is released under the GNU General Public Licence |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
"Chris F.A. Johnson" <cfajohnson@gmail.com> writes:
> On 2006-08-26, Doug Ritschel wrote: >> i=0 >> while read line; do >> i = `expr $i + 1` >> done < /etc/hosts >> echo $i > > Second, you were not running it (with the error fixed) in a Bourne > shell. If you were, you would still have seen '0'. In a Bourne > shell, the redirecion alone is enough to force a subshell. Are you sure? $ cat test.sh i=0 while read line; do i=$(($i + 1)); done </etc/hosts echo $i $ ash test.sh 24 $ bash test.sh 24 $ zsh test.sh 24 Any pointers to standards which support your claim? -- Best regards, _ _ .o. | Liege of Serenly Enlightened Majesty of o' \,=./ `o ..o | Computer Science, Michal "mina86" Nazarewicz (o o) ooo +--<mina86*tlen.pl>--<jid:mina86*jabber.org>--ooO--(_)--Ooo-- |
|
|
|
#8 |
|
Messages: n/a
Hébergeur: |
2006-08-27, 13:57(+02), Michal Nazarewicz:
> "Chris F.A. Johnson" <cfajohnson@gmail.com> writes: > >> On 2006-08-26, Doug Ritschel wrote: >>> i=0 >>> while read line; do >>> i = `expr $i + 1` >>> done < /etc/hosts >>> echo $i >> >> Second, you were not running it (with the error fixed) in a Bourne >> shell. If you were, you would still have seen '0'. In a Bourne >> shell, the redirecion alone is enough to force a subshell. > > Are you sure? > > $ cat test.sh > i=0 > while read line; do i=$(($i + 1)); done </etc/hosts > echo $i > $ ash test.sh > 24 > $ bash test.sh > 24 > $ zsh test.sh > 24 > > > Any pointers to standards which support your claim? [...] Neither ash, bash or zsh are the Bourne shell. Your ash is not the original ash as it supports $((...)). You can find a Bourne shell as the /bin/sh of Solaris or some very old commercial Unices. The Bourne shell doesn't have $((...)), and there's no standard specifying the Bourne shell. In the Bourne shell, redirection meant fork. Newer shells use some trick to work around that limitation (they save the redirected fds (for restauration afterwards) by dupplicating them on other fds before doing the redirections, which you could do manually with the Bourne shell this way: exec 3<&0 < /etc/hosts while read line do i=`expr "$i" + 1 3<&-` done exec <&3 3<&- ) -- Stéphane |
|
![]() |
| Outils de la discussion | |
|
|