首页 sh脚本变量赋值时同时执行命令时的环境问题
文章
取消

sh脚本变量赋值时同时执行命令时的环境问题

在v2ex看到一个问题:

允许在一个命令之前立即发生一个或多个变量赋值,这些赋值为跟随着的命令更改环境变量,这个赋值的影响是暂时的。 那为什么:

1
2
int=100
int=10 echo $(($int - 10))

结果是 90 而不是 0 其实是这样:

1
2
3
int=100
int=10 echo $(($int - 10))
echo $int

sh -x 输出:

1
2
3
4
5
+ int=100
+ int=10 echo 90
90
+ echo 100
100
1
2
3
int=100
int=10 echo $((int=$int - 10))
echo $int

sh -x 输出:

1
2
3
4
5
+ int=100
+ int=10 echo 90
90
+ echo 90
90
1
2
3
4
int=100
xx=10 echo $((int=$int - 10))
echo $int
echo $xx

sh -x 输出:

1
2
3
4
5
6
+ int=100
+ xx=10 echo 90
90
+ echo 90
90
+ echo

所以:

1
2
3
int=100
int=10 echo $(($int - 10))
echo int

等同于:

1
2
3
parent=100
child=10 echo $(($parent-10))
echo $parent

输出:

1
2
3
4
5
+ parent=100
+ child=10 echo 90
90
+ echo 100
100

下面这行:

int=10 echo $(($int - 10))

其实是开了一个新的子环境,并且子环境可以访问全部父环境变量,因为“允许在一个命令之前立即发生一个或多个变量赋值”,所以先执行echo命令,然后做赋值int=10,其实这个int是子环境新建的一个变量,与主环境int是两个不同的变量,换成C语言(linux是C写的,所以设计思想往C靠拢):

1
2
3
4
5
6
int num = 100;
{
    printf("%d\n",num-10);
    int num = 10;
}
printf("%d\n",num);

输出:

90

100

学过C的都应该知道,子作用域新建变量与父作用域变量重名时,子作用域变量会覆盖父作用域变量,当子作用域结束时,子作用域变量被销毁,父作用域变量恢复可见状态,所以出现以上情况。

知识共享许可协议 本文由作者按照 CC BY-SA 4.0 进行授权