Setting variables inside a Bash loop

2019-07-19 07:04发布

问题:

Just started learning Linux Bash Shell Programming, and I just don't know if I understood it correctly. Looking at the sample program below:

#!/bin/bash
n=1
sumRSS=1000
sumSZ=2000

echo Before sumRSS=$sumRSS sumSZ=$sumSZ
ps -ly | while
read c1 c2 c3 c4 c5 c6 c7 c8 c9 c10
do
    if (( n>1 ))
    then
        echo n=$n rss=$sumRSS sz=$sumSZ
        ((sumRSS = sumRSS +  c8))
        ((sumSZ = sumSZ + c9))

    fi
    ((n++))
done

echo Sum of RSS = $sumRSS
echo Sum of SZ = $sumSZ

The output:

Before sumRSS=1000 sumSZ=2000
n=2 rss=1000 sz=2000
n=3 rss=2368 sz=29118
n=4 rss=3792 sz=55644
n=5 rss=4780 sz=82679
Sum of RSS = 1000
Sum of SZ = 2000

I don't know why the sum still goes back to RSS=1000 and SZ=2000. I actually was expecting RSS=4780 and SZ=82679.

I know I am missing something basic. I am learning bash by writing simple scripts.

回答1:

you should avoid the pipe as @linuxfan proposes. You can change your code to:

while read c1 c2 c3 c4 c5 c6 c7 c8 c9 c10
do
    ...
done < <(ps -ly)

this way your variables stay in the same scope.



回答2:

ps -ly | while

You notice the pipe character, "|", which creates two processes. As you know, the environment variables can not be exported from a process to its parent (only to its descendants). So the variables used in the process after the pipe, which is your while statement and its body, can be read and written, but once the process terminates, they get the value they had before.

Indeed, the above line of code creates two processes: one is ps, the output of which is passed to another process, which is another bash. Both processes receive a copy of the initial environment (i.e., the variables), and both processes can modify their copy. But the original process environment is never touched!