shell 里面 declare -r 和 readonly 命令的区别
看shell写数组时候, man bash 数组部分提到了好几个声明数组的命令
The declare, local, and readonly builtins each accept a -a option to specify an indexed array and a -A option to specify an associative array. If both options are supplied, -A takes precedence. The read builtin accepts a -a option to assign a list of words read from the standard input to an array. The set and declare builtins display array values in a way that allows them to be reused as assignments.
通过翻找man bash的其他部分资料, 比如
declare [-aAfFgiIlnrtux] [-p] [name[=value] ...]
typeset [-aAfFgiIlnrtux] [-p] [name[=value] ...]
local [option] [name[=value] ... | - ]
readonly [-aAf] [-p] [name[=word] ...]
还有
- https://www.cnblogs.com/wfwenchao/p/6139039.html Linux set、env、declare、export显示shell变量的区别 - WFApple - 博客园
- https://www.cnblogs.com/qlqwjy/p/9075766.html linux中set、unset、export、env、declare,readonly的区别以及用法 - QiaoZhi - 博客园
- https://www.cnblogs.com/J-YANG/p/15920067.html 举例说明Linux shell中local、export的常用用法和要注意的问题 - J&YANG - 博客园
大概知道了这些东西生成有什么区别
但我没看到有人说declare -r和readonly什么区别的
自己搜不来就问问ai, 但是不知道ai说的东西对不对, 总之参考一下吧
ai问的是腾讯CodeBuddy(原来叫腾讯云代码助手或者腾讯云copilot?), 模型用的是deepseek-v3
在Shell脚本中,declare -r和readonly都用于将变量设置为只读(不可修改),但它们的区别主要体现在以下方面:
1. 来源与兼容性
-
readonly- 是POSIX标准的一部分,兼容所有符合POSIX的Shell(如
sh、bash、dash、ksh等)。 - 更通用,适合需要跨Shell环境运行的脚本。
- 是POSIX标准的一部分,兼容所有符合POSIX的Shell(如
-
declare -r- 是
bash的内置命令(也存在于ksh和zsh中),但非POSIX标准。 - 仅在支持
declare的Shell中有效,例如在dash中会报错。
- 是
2. 功能扩展
-
declare -r- 属于
declare命令的一部分,可以同时声明其他属性(如整数类型-i、大小写转换-u/-l等)。 - 例如:
declare -r -i NUM=10 # 同时声明为只读和整数
- 属于
-
readonly- 仅支持只读属性,无法结合其他类型声明。
3. 作用域
-
函数内的行为
declare -r在函数内声明的变量默认是局部(local)的(除非加-g选项)。readonly在函数内声明的变量默认是全局的。
示例:
func() { declare -r LOCAL_VAR="local" readonly GLOBAL_VAR="global" } func echo "$GLOBAL_VAR" # 输出 "global" echo "$LOCAL_VAR" # 报错或空值(变量已随函数退出销毁)
4. 批量操作
-
readonly
可以一次性标记多个变量为只读:readonly VAR1 VAR2 VAR3 -
declare -r
通常需要分开声明:declare -r VAR1="value1" declare -r VAR2="value2"
5. 显示只读变量
-
readonly -p
列出当前所有只读变量(POSIX兼容方式)。 -
declare -r -p
仅显示通过declare -r声明的变量(bash特有)。
总结建议
- 优先用
readonly:若需要脚本兼容性强(如/bin/sh环境)。 - 选择
declare -r:若脚本明确依赖bash,且需要结合其他属性(如整数、数组等)。
两者在只读功能上等效,但根据场景选择更合适的命令能提升脚本的可移植性和灵活性。
闲着没事又去尝试了一下腾讯CodeBuddy的其他模型效果;
先去问了混元, 回答和deepseek-v3除了格式略有不同以外内容完全一样;
再去问deepseek-r1, 它去回顾对话历史了... 于是有了一些思考, 然后把格式又整理了一下, 加了速查表, 完善了demo展示;
实际上内容差不太多, 这边就折叠起来吧
点击查看
好的,我现在要分析一下用户的问题。用户再次询问了Shell中declare -r和readonly的区别,看起来可能是在之前的对话中没有完全理解,或者想确认更多细节。我需要回顾之前的回答,看看是否有遗漏或需要补充的地方。
首先,用户可能是在学习Shell脚本,特别是bash,所以需要明确这两个命令的异同。之前的回答已经涵盖了来源、兼容性、功能扩展、作用域、批量操作和显示变量等方面。但用户再次提问,可能需要更简明的总结,或者更深入的例子。
接下来,我需要检查之前的回答是否有错误。比如,关于作用域部分,declare -r在函数内默认是局部变量,而readonly是全局的,这个是正确的。但可能需要进一步解释为什么会有这样的差异,或者是否在所有Shell中都是如此。
另外,用户可能对实际应用场景更感兴趣,比如在编写可移植脚本时应该选择哪个命令,或者在性能上有没有差异。虽然之前的回答提到了兼容性,但可能需要更强调实际选择建议。
还要考虑用户是否有隐藏的需求,比如是否遇到了相关的问题,比如变量作用域的问题,或者批量声明时的麻烦。这时候可能需要提供更具体的例子或者解决方法。
另外,需要注意是否需要区分不同Shell的表现,比如在bash和zsh中的行为是否一致,或者是否有其他Shell的特定情况。比如,declare在ksh中的表现可能不同,但用户可能主要关心的是bash。
最后,要确保回答结构清晰,避免重复,同时补充新的信息或更直观的例子。可能需要用表格对比两者的区别,或者用更简洁的语言总结关键点,方便用户快速理解。
在 Shell 脚本中,declare -r 和 readonly 都用于将变量设为只读(不可修改),但它们的区别主要体现在以下几个方面:
一、语法来源与兼容性
| 命令 | 兼容性 | 适用场景 |
|---|---|---|
readonly |
POSIX 标准,兼容所有 Shell(如 sh、dash、bash、ksh 等) |
跨 Shell 脚本,强调可移植性 |
declare -r |
仅限 Bash(也支持 ksh 和 zsh,但非 POSIX 标准) |
Bash 专属脚本,需明确环境 |
示例验证兼容性:
在 dash(Ubuntu 默认的 /bin/sh)中执行 declare -r 会报错:
$ dash
$ declare -r VAR=1
dash: 1: declare: not found
二、功能扩展性
| 命令 | 额外功能 |
|---|---|
readonly |
仅支持声明变量为只读 |
declare -r |
可结合其他属性(如整数、数组、大小写转换等) |
示例:声明只读整数变量
declare -r -i NUM=10 # 同时声明为只读和整数
NUM=20 # 报错:只读变量不可修改
三、变量作用域
| 命令 | 函数内的行为 |
|---|---|
readonly |
默认声明为全局变量(即使函数内调用) |
declare -r |
默认声明为局部变量(除非用 -g 选项) |
示例:作用域差异
func() {
declare -r LOCAL_VAR="local" # 局部只读变量
readonly GLOBAL_VAR="global" # 全局只读变量
}
func
echo "$GLOBAL_VAR" # 输出 "global"
echo "$LOCAL_VAR" # 输出空(变量已随函数退出销毁)
四、批量操作
| 命令 | 批量声明能力 |
|---|---|
readonly |
支持一次性声明多个变量:readonly VAR1 VAR2 |
declare -r |
需逐个声明:declare -r VAR1; declare -r VAR2 |
示例:批量声明只读变量
readonly PI=3.14 E=2.718 # 一次性声明多个只读变量
五、查看只读变量
| 命令 | 行为 |
|---|---|
readonly -p |
列出所有只读变量(POSIX 兼容) |
declare -r -p |
列出通过 declare -r 声明的变量(Bash 特有) |
总结与选择建议
-
优先用
readonly- 需要跨 Shell 兼容(如
/bin/sh脚本)。 - 仅需简单声明只读变量,无需额外属性。
- 需要跨 Shell 兼容(如
-
选择
declare -r- 脚本明确依赖 Bash(如
#!/bin/bash)。 - 需结合其他变量属性(如整数、数组、大小写转换等)。
- 脚本明确依赖 Bash(如
关键区别速查表
| 特性 | readonly |
declare -r |
|---|---|---|
| 兼容性 | 所有 POSIX Shell | 仅 Bash/ksh/zsh |
| 作用域 | 全局 | 局部(函数内) |
| 批量声明 | 支持 | 不支持 |
| 额外属性 | 不支持 | 支持(如 -i) |
| 查看变量 | readonly -p |
declare -r -p |
根据脚本需求选择工具,可提升代码的可移植性和灵活性。

浙公网安备 33010602011771号