Bash local -I 的属性继承:同名变量保住了值,整数运算规则为什么还要另外继承
把外层整数变量复制进函数,打印的初值同样是7,不代表两个变量保留了相同属性。Bash变量既有值,也可能带整数、大小写转换等属性。local amount="$amount" 明确复制了值;在本文关闭自动继承选项的条件下,它不会同时把外层的整数属性复制进来。
示例在 GNU Bash 5.2.37 上运行,使用该版本支持的 local -I。保存为 demo.sh,用 bash --noprofile --norc demo.sh 执行,不要用 sh,也不要 source 到当前交互环境。程序主动关闭 localvar_inherit,让对比不受该选项影响;所有算式都是代码中的固定文字,不读取外部输入。
AI模型生成概念示意:一条路径只复制方块,另一条路径同时复制方块与齿轮;方块代表值,齿轮代表会影响赋值行为的属性,不是Bash内存布局。
完整实验
#!/usr/bin/env bash
set -u
shopt -u localvar_inherit
declare -i amount=7
copy_value() {
local amount="$amount"
declare -p amount
amount='2+3'
printf 'copy-value=%s\n' "$amount"
}
inherit_all() {
local -I amount
declare -p amount
amount='2+3'
printf 'inherit-all=%s\n' "$amount"
}
declare_explicitly() {
local -i amount=7
amount='2+3'
printf 'explicit-integer=%s\n' "$amount"
}
copy_value
inherit_all
declare_explicitly
printf 'outer=%s\n' "$amount"
missing_source() {
local -I batch29_missing_variable
printf 'missing-source=%s\n' "${batch29_missing_variable-unset}"
}
missing_source本地实际输出
declare -- amount="7" copy-value=2+3 declare -i amount="7" inherit-all=5 explicit-integer=5 outer=7 missing-source=unset
第一段 declare -- amount="7" 中没有 -i,说明局部 amount 是普通变量。之后赋入文字 2+3,得到的仍是原样文字。第二段 declare -i amount="7" 则保留整数属性,后续赋值时会把 2+3 当算术表达式求值,输出5。区别不在引号是否写全,而在接收赋值的变量具有什么属性。
local -I 会从可见的外层同名变量继承值和属性,但不继承 nameref 属性。示例的 inherit_all 只声明一次,就继承了外层初值7与整数属性。函数退出后,外层 amount 仍为7;继承这些设置不等于把局部变量变成同一个可写存储位置。
declare_explicitly 使用 local -i amount=7,同样得到5。对一个本来就要求整数计数的函数,显式声明往往更容易阅读:它直接说明函数自己需要什么。-I 更适合确实要延续调用环境中同名变量约定的场景,需要同时理解这种依赖。
边界与使用约定
missing-source 展示外层没有同名变量时的情况:local -I 创建的局部变量起初仍未赋值。这里通过带备用值的参数展开显示 unset,避免 set -u 因直接读取未设置变量而终止脚本。继承选项不会凭空替你提供一个业务默认值。
如果把 localvar_inherit 打开,普通 local 的默认继承行为也会改变。排查机器之间输出差异时,应一起记录 Bash 版本与相关 shell 选项。本文显式关掉它,目的是让 -I 的作用能够单独观察;在共享函数库中不要随意更改调用者的全局选项。
整数属性不是输入校验器。它会触发算术求值,所以不能把不可信文本直接赋给带 -i 的变量,再期待它只接受十进制数字。业务输入应先按允许的字符、范围和进制验证。本例的 2+3 是为了展示机制而故意写入的固定表达式,不能照搬成任意输入计算器。
参考资料
官方资料核验日期:2026-10-02。


