为何 shell 脚本变量传入任意方法后会被内部的循环体的同名遍历变量的值所覆盖?

2023-02-23 18:57:57 +08:00
 mylovesaber

源码(后文 listA 和 listB 数组简称 A 数组和 B 数组):

#!/bin/bash
AA(){
    for ii in "${listB[@]}"; do   #|
        :                         #| ==> 这 AA 方法中的 for 循环目的是遍历 B 数组,但什么都不做。
    done                          #|
}

listA=(1)                  #
listB=(a b c d)            #___这四行仅仅定义和打印出两个数组中的元素(后文结果中的前两行内容)
echo "listA: ${listA[@]}"  #
echo "listB: ${listB[@]}"  #

for ii in "${listA[@]}"; do
    echo "在 AA 方法前的值: ${ii}" # 传 ii 给方法 AA 前看值是多少
    AA "${ii}"                  # 将遍历的 ii 传给方法 AA
    echo "在 AA 方法后的值: ${ii}" # 传 ii 给方法 AA 后看值是多少
done

输出结果:

listA: 1
listB: a b c d
在 AA 方法前的值: 1
在 AA 方法后的值: d

可以看到:遍历数组 A 时所用的变量 ii 和方法内遍历数组 B 时所用变量是相同的,但这变量 ii 为何是全局变量啊?我尝试了以下写法:

  1. 只在遍历数组 A 之前加入 local ii
  2. 只在方法 AA 中遍历数组 B 之前加入 local ii
  3. 以上两个写法都安排上

好像最终输出的都是 listB 数组的最后一个元素值,这又是怎么个操作? 有点懵,以前没遇到过,有大佬解惑吗?

1211 次点击
所在节点    Linux
7 条回复
mylovesaber
2023-02-23 19:06:21 +08:00
问错了。。。等重新编辑。。。
mylovesaber
2023-02-23 19:08:15 +08:00
@mylovesaber 好像没问错。。。这 ii 不应该是专属于当前 for 循环的变量么?为何会成为了全局变量?
momocraft
2023-02-23 19:11:54 +08:00
sh (bash) 的变量不是 lexical scope, 是 dynamic scope

AA 有了 local ii 后不应该覆盖外面的 ii 能把你的完整代码贴出来看看吗
mylovesaber
2023-02-23 19:23:00 +08:00
在 AA 方法中的 for 循环前后都加上 `echo $1`,可以看到打印的两次 $1 结果都是 A 数组中的元素值 1 ,说明传进去的的确是 1 ,但这是 ii 的值啊,数组内部 ii 值被循环中的 ii 替换后,为何 $1 值没变?
mylovesaber
2023-02-23 19:24:55 +08:00
@momocraft 这个说法第一次听说,我一楼发的那个就是完整的测试源码,可以得到方法内部的 for 循环中 ii 值的确可以把方法外部套的循环中的 ii 值给替换掉的结论,你直接复制粘贴删掉注释运行就能看到结果
mylovesaber
2023-02-23 19:35:26 +08:00
@momocraft 不好意思刚刚可能有什么操作失误的地方,local 只能用在方法内,刚刚查了下好像明白 local 生效的原因了,但有点诧异为啥别的语言 for 循环的类似 shell 的 ii 位置只能作用于该循环内,而方法内不声明 local 的话,shell for 循环中的 ii 会是全局变量
mylovesaber
2023-02-23 19:37:03 +08:00

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/918639

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX