Linux - bash while subshell中变量操作的问题
需求
演示一个简单的需求:使用bash语言,对1到5进行累加,并输出结果。
代码
$ cat while_loop_operate_global_variable.sh
#!/bin/bash
# Author: thesre
# Date:
total=0
echo "Let's check the initial value of total:"
echo "$total"
echo ""
num_list=`seq 1 5`
echo "$num_list"| while read i
do
total=`echo $total + $i| bc`
echo $total
done
echo ""
echo "OK, let's check the value of total out of the while loop."
echo $total
Run结果
[thesre@centos8 ~]$ ./while_loop_operate_global_variable.sh
Let's check the initial value of total:
0
1
3
6
10
15
OK, let's check the value of total out of the while loop.
0
可以看到,在while loop中有对变量进行累加。但,最终结果,却是初始值0!
这是为何?
分析
这是因为while运行在subshell里,当while运行完后,其里面的变量被废弃。因此在最后打印的还是初始值。
解决
要解决该问题,需要避免在subshell中操作变量。
方法一:我们可以使用here string的方式来让操作变量的代码放在脚本main shell中。
[thesre@centos8 ~]$ cat while_loop_operate_global_variable.sh
#!/bin/bash
# Author: thesre
# Date:
total=0
echo "Let's check the initial value of total:"
echo "$total"
echo ""
num_list=`seq 1 5`
while read i
do
total=`echo $total + $i| bc`
echo $total
done <<< "$num_list"
echo ""
echo "OK, let's check the value of total out of the while loop."
echo $total
方法二:我们可以使用process substitution的方式来让操作变量的代码放在脚本main shell中。
#!/bin/bash
# Author: thesre
# Date:
total=0
echo "Let's check the initial value of total:"
echo "$total"
echo ""
while read i
do
total=`echo $total + $i| bc`
echo $total
done < <(seq 1 5)
echo ""
echo "OK, let's check the value of total out of the while loop."
echo $total
Run效果
[thesre@centos8 ~]$ ./while_loop_operate_global_variable.sh
Let's check the initial value of total:
0
1
3
6
10
15
OK, let's check the value of total out of the while loop.
15
总结
在脚本程序出现不符合预期的情况时,需分析进程间的关系。如本案,操作变量的代码在subshell中,无论如何操作都不会影响在main shell中的变量。
参考资料
https://tldp.org/LDP/abs/html/gotchas.html#BADREAD0 #管道输出到任一命令均会有该问题
https://tldp.org/LDP/abs/html/process-sub.html #process substitution