Hi,
I am trying something like the following, with a configuration file containing a token and a directory in a line, depending on the tokens, certain actions should be taken later. Validating the configuration file whether all the required/optional tokens are in the file should go like this:
-----a.txt---------------------- A directory1 B directory2 C directory3 --------------------------------
-----a.sh----------------------- #!/bin/bash
HAS_A=0 HAS_B=0 HAS_C=0 cat a.txt | while read i ; do if [ "`echo $i | awk '{ print $1 }'`" = "A" ]; then HAS_A=1 fi if [ "`echo $i | awk '{ print $1 }'`" = "B" ]; then HAS_B=1 fi if [ "`echo $i | awk '{ print $1 }'`" = "C" ]; then HAS_C=1 fi echo "A: $HAS_A B: $HAS_B C: $HAS_C" done echo "Final A: $HAS_A B: $HAS_B C: $HAS_C" --------------------------------
Result is:
-------------------------------- $ ./a.sh A: 1 B: 0 C: 0 A: 1 B: 1 C: 0 A: 1 B: 1 C: 1 Final A: 0 B: 0 C: 0 --------------------------------
It seems to be a bug to me, the envvars lose their values they gained in the loop. It's an ancient bug I must add, I just rechecked it and bash in RedHat 7.1 behaves the same. How can I preserve the variables' values? Putting "export" in front of every assignments doesn't help.
Best regards, Zoltán Böszörményi
Zoltan Boszormenyi írta:
Hi,
I am trying something like the following, with a configuration file containing a token and a directory in a line, depending on the tokens, certain actions should be taken later. Validating the configuration file whether all the required/optional tokens are in the file should go like this:
-----a.txt---------------------- A directory1 B directory2 C directory3
-----a.sh----------------------- #!/bin/bash
HAS_A=0 HAS_B=0 HAS_C=0 cat a.txt | while read i ; do if [ "`echo $i | awk '{ print $1 }'`" = "A" ]; then HAS_A=1 fi if [ "`echo $i | awk '{ print $1 }'`" = "B" ]; then HAS_B=1 fi if [ "`echo $i | awk '{ print $1 }'`" = "C" ]; then HAS_C=1 fi echo "A: $HAS_A B: $HAS_B C: $HAS_C" done echo "Final A: $HAS_A B: $HAS_B C: $HAS_C"
Result is:
$ ./a.sh A: 1 B: 0 C: 0 A: 1 B: 1 C: 0 A: 1 B: 1 C: 1 Final A: 0 B: 0 C: 0
It seems to be a bug to me, the envvars lose their values they gained in the loop. It's an ancient bug I must add, I just rechecked it and bash in RedHat 7.1 behaves the same. How can I preserve the variables' values? Putting "export" in front of every assignments doesn't help.
Best regards, Zoltán Böszörményi
I just tried to narrow the test for the bug:
---b.sh------------------------- #!/bin/bash
X=0 A=2 while [ $A -gt 0 ]; do X=1 A=$(($A - 1)) echo "A: $A X: $X" done echo "Final A: $A X: $X" --------------------------------
Result:
-------------------------------- $ ./b.sh A: 1 X: 1 A: 0 X: 1 Final A: 0 X: 1 --------------------------------
The variables here keep their values. Hm. Then the bug may come from the "cat a.txt | while read i; do" construct, maybe another sub-shell is opened for this loop. But then putting "export" in front of the assignments inside the loop should solve this but it doesn't. It still seems to be a bug to me somewhere.
Can someone help me? Thanks in advance and best regards, Zoltán Böszörményi
Zoltan Boszormenyi wrote:
Zoltan Boszormenyi írta:
Hi,
I am trying something like the following, with a configuration file containing a token and a directory in a line, depending on the tokens, certain actions should be taken later. Validating the configuration file whether all the required/optional tokens are in the file should go like this:
-----a.txt---------------------- A directory1 B directory2 C directory3
-----a.sh----------------------- #!/bin/bash
HAS_A=0 HAS_B=0 HAS_C=0 cat a.txt | while read i ; do if [ "`echo $i | awk '{ print $1 }'`" = "A" ]; then HAS_A=1 fi if [ "`echo $i | awk '{ print $1 }'`" = "B" ]; then HAS_B=1 fi if [ "`echo $i | awk '{ print $1 }'`" = "C" ]; then HAS_C=1 fi echo "A: $HAS_A B: $HAS_B C: $HAS_C" done echo "Final A: $HAS_A B: $HAS_B C: $HAS_C"
Result is:
$ ./a.sh A: 1 B: 0 C: 0 A: 1 B: 1 C: 0 A: 1 B: 1 C: 1 Final A: 0 B: 0 C: 0
It seems to be a bug to me, the envvars lose their values they gained in the loop. It's an ancient bug I must add, I just rechecked it and bash in RedHat 7.1 behaves the same. How can I preserve the variables' values? Putting "export" in front of every assignments doesn't help.
Best regards, Zoltán Böszörményi
I just tried to narrow the test for the bug:
---b.sh------------------------- #!/bin/bash
X=0 A=2 while [ $A -gt 0 ]; do X=1 A=$(($A - 1)) echo "A: $A X: $X" done echo "Final A: $A X: $X"
Result:
$ ./b.sh A: 1 X: 1 A: 0 X: 1 Final A: 0 X: 1
The variables here keep their values. Hm. Then the bug may come from the "cat a.txt | while read i; do" construct, maybe another sub-shell is opened for this loop. But then putting "export" in front of the assignments inside the loop should solve this but it doesn't. It still seems to be a bug to me somewhere.
Yes, the "cat a.txt | while read i; do ..." construct does cause the "while" loop to be executed in a subshell. Everything is working as it should. The only bug is in your understanding of how processes and environments work. Each process has its very own environment, and exporting a variable causes a child process's initial enviromnent to receive a copy of that variable. Nothing the child subsequently does to that copy has any effect on the parent process.
Hopefully you've got a copy of the bash FAQ installed on your system (/usr/share/doc/bash-3.0/FAQ on mine). Take a look at answer E4.
On Mon, 2005-09-26 at 07:12 +0200, Zoltan Boszormenyi wrote:
Hi,
I am trying something like the following, with a configuration file containing a token and a directory in a line, depending on the tokens, certain actions should be taken later. Validating the configuration file whether all the required/optional tokens are in the file should go like this:
-----a.txt---------------------- A directory1 B directory2 C directory3
-----a.sh----------------------- #!/bin/bash
HAS_A=0 HAS_B=0 HAS_C=0 cat a.txt | while read i ; do if [ "`echo $i | awk '{ print $1 }'`" = "A" ]; then HAS_A=1 fi if [ "`echo $i | awk '{ print $1 }'`" = "B" ]; then HAS_B=1 fi if [ "`echo $i | awk '{ print $1 }'`" = "C" ]; then HAS_C=1 fi echo "A: $HAS_A B: $HAS_B C: $HAS_C" done echo "Final A: $HAS_A B: $HAS_B C: $HAS_C"
Result is:
$ ./a.sh A: 1 B: 0 C: 0 A: 1 B: 1 C: 0 A: 1 B: 1 C: 1 Final A: 0 B: 0 C: 0
It seems to be a bug to me, the envvars lose their values they gained in the loop. It's an ancient bug I must add, I just rechecked it and bash in RedHat 7.1 behaves the same. How can I preserve the variables' values? Putting "export" in front of every assignments doesn't help.
Careful, those are not environment variables as you imply by the statement above when you call them envars.
This is caused by the scope of variables. You are actually creating 2 different copies of each HAS_A, HAS_B, and HAS_C. The first exists outside the while loop, the second exists only inside the while loop. And all only exist while the script is executing. Even though the name is the same, the scope is different.
Even if they were environment variables and had a permanent life outside the script, the value assigned still only lasts as long as the calling process lives (in this case the while loop). I tested this to verify.
Best regards, Zoltán Böszörményi
On Mon, 2005-09-26 at 02:11 -0500, Jeff Vian wrote:
On Mon, 2005-09-26 at 07:12 +0200, Zoltan Boszormenyi wrote:
Hi,
I am trying something like the following, with a configuration file containing a token and a directory in a line, depending on the tokens, certain actions should be taken later. Validating the configuration file whether all the required/optional tokens are in the file should go like this:
-----a.txt---------------------- A directory1 B directory2 C directory3
-----a.sh----------------------- #!/bin/bash
HAS_A=0 HAS_B=0 HAS_C=0 cat a.txt | while read i ; do if [ "`echo $i | awk '{ print $1 }'`" = "A" ]; then HAS_A=1 fi if [ "`echo $i | awk '{ print $1 }'`" = "B" ]; then HAS_B=1 fi if [ "`echo $i | awk '{ print $1 }'`" = "C" ]; then HAS_C=1 fi echo "A: $HAS_A B: $HAS_B C: $HAS_C" done echo "Final A: $HAS_A B: $HAS_B C: $HAS_C"
Result is:
$ ./a.sh A: 1 B: 0 C: 0 A: 1 B: 1 C: 0 A: 1 B: 1 C: 1 Final A: 0 B: 0 C: 0
It seems to be a bug to me, the envvars lose their values they gained in the loop. It's an ancient bug I must add, I just rechecked it and bash in RedHat 7.1 behaves the same. How can I preserve the variables' values? Putting "export" in front of every assignments doesn't help.
Careful, those are not environment variables as you imply by the statement above when you call them envars.
This is caused by the scope of variables. You are actually creating 2 different copies of each HAS_A, HAS_B, and HAS_C. The first exists outside the while loop, the second exists only inside the while loop. And all only exist while the script is executing. Even though the name is the same, the scope is different.
Even if they were environment variables and had a permanent life outside the script, the value assigned still only lasts as long as the calling process lives (in this case the while loop). I tested this to verify.
Best regards, Zoltán Böszörményi
The change in the script [1] makes this work as you expected [2].
---[1]------------------------------------------------------
#!/bin/bash
exec < a.txt
HAS_A=0 HAS_B=0 HAS_C=0 while read i ; do if [ "`echo $i | awk '{ print $1 }'`" = "A" ]; then HAS_A=1 fi if [ "`echo $i | awk '{ print $1 }'`" = "B" ]; then HAS_B=1 fi if [ "`echo $i | awk '{ print $1 }'`" = "C" ]; then HAS_C=1 fi echo "A: $HAS_A B: $HAS_B C: $HAS_C" done echo "Final A: $HAS_A B: $HAS_B C: $HAS_C"
----[2]---------------------------------------- [jeff@eagle test]$ ./a.sh A: 1 B: 0 C: 0 A: 1 B: 1 C: 0 A: 1 B: 1 C: 1 Final A: 1 B: 1 C: 1
In order to read a file without opening a sub shell do:
while read LINE; do
echo $LINE blah blah
done < file.txt
Gilboa
On Mon, 2005-09-26 at 03:30 -0500, Jeff Vian wrote:
On Mon, 2005-09-26 at 02:11 -0500, Jeff Vian wrote:
On Mon, 2005-09-26 at 07:12 +0200, Zoltan Boszormenyi wrote:
Hi,
I am trying something like the following, with a configuration file containing a token and a directory in a line, depending on the tokens, certain actions should be taken later. Validating the configuration file whether all the required/optional tokens are in the file should go like this:
-----a.txt---------------------- A directory1 B directory2 C directory3
-----a.sh----------------------- #!/bin/bash
HAS_A=0 HAS_B=0 HAS_C=0 cat a.txt | while read i ; do if [ "`echo $i | awk '{ print $1 }'`" = "A" ]; then HAS_A=1 fi if [ "`echo $i | awk '{ print $1 }'`" = "B" ]; then HAS_B=1 fi if [ "`echo $i | awk '{ print $1 }'`" = "C" ]; then HAS_C=1 fi echo "A: $HAS_A B: $HAS_B C: $HAS_C" done echo "Final A: $HAS_A B: $HAS_B C: $HAS_C"
Result is:
$ ./a.sh A: 1 B: 0 C: 0 A: 1 B: 1 C: 0 A: 1 B: 1 C: 1 Final A: 0 B: 0 C: 0
It seems to be a bug to me, the envvars lose their values they gained in the loop. It's an ancient bug I must add, I just rechecked it and bash in RedHat 7.1 behaves the same. How can I preserve the variables' values? Putting "export" in front of every assignments doesn't help.
Careful, those are not environment variables as you imply by the statement above when you call them envars.
This is caused by the scope of variables. You are actually creating 2 different copies of each HAS_A, HAS_B, and HAS_C. The first exists outside the while loop, the second exists only inside the while loop. And all only exist while the script is executing. Even though the name is the same, the scope is different.
Even if they were environment variables and had a permanent life outside the script, the value assigned still only lasts as long as the calling process lives (in this case the while loop). I tested this to verify.
Best regards, Zoltán Böszörményi
The change in the script [1] makes this work as you expected [2].
---[1]------------------------------------------------------
#!/bin/bash
exec < a.txt
HAS_A=0 HAS_B=0 HAS_C=0 while read i ; do if [ "`echo $i | awk '{ print $1 }'`" = "A" ]; then HAS_A=1 fi if [ "`echo $i | awk '{ print $1 }'`" = "B" ]; then HAS_B=1 fi if [ "`echo $i | awk '{ print $1 }'`" = "C" ]; then HAS_C=1 fi echo "A: $HAS_A B: $HAS_B C: $HAS_C" done echo "Final A: $HAS_A B: $HAS_B C: $HAS_C"
----[2]---------------------------------------- [jeff@eagle test]$ ./a.sh A: 1 B: 0 C: 0 A: 1 B: 1 C: 0 A: 1 B: 1 C: 1 Final A: 1 B: 1 C: 1
Happy to help.
Gilboa
On Mon, 2005-09-26 at 11:55 +0200, Zoltan Boszormenyi wrote:
Hi,
Gilboa Davara írta:
In order to read a file without opening a sub shell do:
while read LINE; do
echo $LINE blah blah
done < file.txt
Gilboa
Thanks for all who answered, this is the solution that fits my taste.
Best regards, Zoltán Böszörményi
--- Jeff Vian jvian10@charter.net wrote:
On Mon, 2005-09-26 at 02:11 -0500, Jeff Vian wrote:
On Mon, 2005-09-26 at 07:12 +0200, Zoltan Boszormenyi wrote:
Hi,
I am trying something like the following, with a configuration file containing a token and a directory in a line, depending on the tokens, certain actions should be taken later. Validating the configuration file whether all the required/optional tokens are in the file should go like this:
-----a.txt---------------------- A directory1 B directory2 C directory3
-----a.sh----------------------- #!/bin/bash
HAS_A=0 HAS_B=0 HAS_C=0 cat a.txt | while read i ; do if [ "`echo $i | awk '{ print $1 }'`" = "A" ]; then HAS_A=1 fi if [ "`echo $i | awk '{ print $1 }'`" = "B" ]; then HAS_B=1 fi if [ "`echo $i | awk '{ print $1 }'`" = "C" ]; then HAS_C=1 fi echo "A: $HAS_A B: $HAS_B C: $HAS_C" done echo "Final A: $HAS_A B: $HAS_B C: $HAS_C"
Result is:
$ ./a.sh A: 1 B: 0 C: 0 A: 1 B: 1 C: 0 A: 1 B: 1 C: 1 Final A: 0 B: 0 C: 0
It seems to be a bug to me, the envvars lose their values they gained in the loop. It's an ancient bug I must add, I just rechecked it and bash in RedHat 7.1 behaves the same. How can I preserve the variables' values? Putting "export" in front of every assignments doesn't help.
Careful, those are not environment variables as you imply by the statement above when you call them envars.
This is caused by the scope of variables. You are actually creating 2 different copies of each HAS_A, HAS_B, and HAS_C. The first exists outside the while loop, the second exists only inside the while loop. And all only exist while the script is executing. Even though the name is the same, the scope is different.
Even if they were environment variables and had a permanent life outside the script, the value assigned still only lasts as long as the calling process lives (in this case the while loop). I tested this to verify.
Best regards, Zoltán Böszörményi
This is also a problem with ksh under linux.
I ran into this very 'sub-shell' problem when converting ksh scripts to run under linux that were developed to run under SCO Unix.
Other versions of System V Unix I have worked with do not have this 'sub-shell' problem either.
This seems to be a Linux issue with the shells.
Then this is a departure from original/standard System V behaviour. Again, all System V based Unixes I have programmed under did have this behaviour.
Anyone converting scritps (as I had to do) will run into this problem/behaviour.
--- Tim Waugh twaugh@redhat.com wrote:
On Mon, Sep 26, 2005 at 06:15:21AM -0700, BRUCE STANLEY wrote:
This seems to be a Linux issue with the shells.
It is correct behaviour, and POSIX-compliant to boot.
Please see the bash FAQ, question E4.
/usr/share/doc/bash-3.0/FAQ
Tim. */
--
fedora-list mailing list fedora-list@redhat.com To unsubscribe: https://www.redhat.com/mailman/listinfo/fedora-list
On Mon, 2005-09-26 at 14:42 -0700, BRUCE STANLEY wrote:
Then this is a departure from original/standard System V behaviour. Again, all System V based Unixes I have programmed under did have this behaviour.
Anyone converting scritps (as I had to do) will run into this problem/behaviour.
I think the key here is the subshell behavior which is to be expected. Scope of variables is important, and a subshell (as has already been stated) cannot affect the values of variables in it's parent.
This behavior is posix compliant, as well as unix standard. (I tried the same on an AIX machine with the same results).
People may run into problems at any time when the original is not 100% posix compliant and/or has been written to take advantage of sometimes lax standards in the OS.
Think of it this way. The fixes you do will make the original better and more standardized in the long run. You are killing bugs. I know the work now is frustrating, but the end product is improved.
--- Tim Waugh twaugh@redhat.com wrote:
On Mon, Sep 26, 2005 at 06:15:21AM -0700, BRUCE STANLEY wrote:
This seems to be a Linux issue with the shells.
It is correct behaviour, and POSIX-compliant to boot.
Please see the bash FAQ, question E4.
/usr/share/doc/bash-3.0/FAQ
Tim. */
--
fedora-list mailing list fedora-list@redhat.com To unsubscribe: https://www.redhat.com/mailman/listinfo/fedora-list
On Mon, 2005-09-26 at 14:42 -0700, BRUCE STANLEY wrote:
Then this is a departure from original/standard System V behaviour. Again, all System V based Unixes I have programmed under did have this behaviour.
Anyone converting scritps (as I had to do) will run into this problem/behaviour.
BTW, On AIX when I tried using bash I had the same effect as I did on Linux. When I tried it with ksh the results were as you obviously expected. The subshell for the cat command was able to modify the values of the variable in the parent.
--- Tim Waugh twaugh@redhat.com wrote:
On Mon, Sep 26, 2005 at 06:15:21AM -0700, BRUCE STANLEY wrote:
This seems to be a Linux issue with the shells.
It is correct behaviour, and POSIX-compliant to boot.
Please see the bash FAQ, question E4.
/usr/share/doc/bash-3.0/FAQ
Tim. */
--
fedora-list mailing list fedora-list@redhat.com To unsubscribe: https://www.redhat.com/mailman/listinfo/fedora-list
I can't remember the title of the clasic KSH book we used in the good old days (it was white with blue lettering if I remember right), but I do not remember it ever saying that ENVs would be local within a 'while' loop. Until Linux, I never had this problem with ksh.
I don't know if that was the case though with bsh (original bourne shell) as we never used it.
--- Jeff Vian jvian10@charter.net wrote:
On Mon, 2005-09-26 at 14:42 -0700, BRUCE STANLEY wrote:
Then this is a departure from original/standard System V behaviour. Again, all System V based Unixes I have programmed under did have this behaviour.
Anyone converting scritps (as I had to do) will run into this problem/behaviour.
BTW, On AIX when I tried using bash I had the same effect as I did on Linux. When I tried it with ksh the results were as you obviously expected. The subshell for the cat command was able to modify the values of the variable in the parent.
--- Tim Waugh twaugh@redhat.com wrote:
On Mon, Sep 26, 2005 at 06:15:21AM -0700, BRUCE STANLEY wrote:
This seems to be a Linux issue with the shells.
It is correct behaviour, and POSIX-compliant to boot.
Please see the bash FAQ, question E4.
/usr/share/doc/bash-3.0/FAQ
Tim. */
--
fedora-list mailing list fedora-list@redhat.com To unsubscribe: https://www.redhat.com/mailman/listinfo/fedora-list
-- fedora-list mailing list fedora-list@redhat.com To unsubscribe: https://www.redhat.com/mailman/listinfo/fedora-list
On Wed, 2005-09-28 at 06:36 -0700, BRUCE STANLEY wrote:
I can't remember the title of the clasic KSH book we used in the good old days (it was white with blue lettering if I remember right), but I do not remember it ever saying that ENVs would be local within a 'while' loop. Until Linux, I never had this problem with ksh.
I don't know if that was the case though with bsh (original bourne shell) as we never used it.
Not the while loop, (that is not scope limiting by itself,) but the 'cat' subshell structure (cat with the output piped to the while loop). In bash it seems to be a subshell and does limit env scope, in ksh it seems not to be. (At least in my testing on AIX.)
--- Jeff Vian jvian10@charter.net wrote:
On Mon, 2005-09-26 at 14:42 -0700, BRUCE STANLEY wrote:
Then this is a departure from original/standard System V behaviour. Again, all System V based Unixes I have programmed under did have this behaviour.
Anyone converting scritps (as I had to do) will run into this problem/behaviour.
BTW, On AIX when I tried using bash I had the same effect as I did on Linux. When I tried it with ksh the results were as you obviously expected. The subshell for the cat command was able to modify the values of the variable in the parent.
--- Tim Waugh twaugh@redhat.com wrote:
On Mon, Sep 26, 2005 at 06:15:21AM -0700, BRUCE STANLEY wrote:
This seems to be a Linux issue with the shells.
It is correct behaviour, and POSIX-compliant to boot.
Please see the bash FAQ, question E4.
/usr/share/doc/bash-3.0/FAQ
Tim. */
--
fedora-list mailing list fedora-list@redhat.com To unsubscribe: https://www.redhat.com/mailman/listinfo/fedora-list
-- fedora-list mailing list fedora-list@redhat.com To unsubscribe: https://www.redhat.com/mailman/listinfo/fedora-list
On Monday, Sep 26th 2005 at 07:12 +0200, quoth Zoltan Boszormenyi:
=>Hi, => =>I am trying something like the following, =>with a configuration file containing a token and =>a directory in a line, depending on the tokens, =>certain actions should be taken later. Validating =>the configuration file whether all the required/optional =>tokens are in the file should go like this: => =>-----a.txt---------------------- =>A directory1 =>B directory2 =>C directory3 =>-------------------------------- => =>-----a.sh----------------------- =>#!/bin/bash => =>HAS_A=0 =>HAS_B=0 =>HAS_C=0 =>cat a.txt | while read i ; do => if [ "`echo $i | awk '{ print $1 }'`" = "A" ]; then => HAS_A=1 => fi => if [ "`echo $i | awk '{ print $1 }'`" = "B" ]; then => HAS_B=1 => fi => if [ "`echo $i | awk '{ print $1 }'`" = "C" ]; then => HAS_C=1 => fi => echo "A: $HAS_A B: $HAS_B C: $HAS_C" =>done =>echo "Final A: $HAS_A B: $HAS_B C: $HAS_C" =>--------------------------------
#!/bin/bash
HAS_A=0 HAS_B=0 HAS_C=0 while read lbl dir do [[ $lbl = A ]] && HAS_A=1 [[ $lbl = B ]] && HAS_B=1 [[ $lbl = C ]] && HAS_C=1 echo "A: $HAS_A B: $HAS_B C: $HAS_C" done < a.txt echo "Final A: $HAS_A B: $HAS_B C: $HAS_C"
cat | while causes the while to be in a subshell.
=>Result is: => =>-------------------------------- =>$ ./a.sh =>A: 1 B: 0 C: 0 =>A: 1 B: 1 C: 0 =>A: 1 B: 1 C: 1 =>Final A: 0 B: 0 C: 0 =>--------------------------------