linux declare命令

declare命令是bash shell的内置命令,用于声明变量和设置变量属性。它可以显示所有变量、创建新变量或修改已有变量的属性。

语法格式

declare [选项] [名称[=值] ...]

命令功能

  • 声明变量并设置变量属性
  • 显示所有变量及其属性
  • 将变量设置为只读、整数、数组等类型
  • 导出变量到子shell环境
  • 设置变量的作用域(局部或全局)

📝 重要说明

  • declare是bash的内置命令,不是外部程序
  • 不指定任何参数时,显示所有变量和函数
  • 变量属性只在当前shell会话中有效
  • 使用-g选项可以创建全局变量(在函数内部)
  • 使用-r设置的只读变量不能被修改或删除

变量属性说明

属性 说明
只读 (readonly) 变量不能被重新赋值或取消设置
整数 (integer) 变量只能存储整数值,赋值时会自动进行整数运算
数组 (array) 变量可以存储多个值,使用索引访问
关联数组 (associative array) 数组使用字符串作为索引(键值对)
导出 (export) 变量会传递给子shell环境
小写 (lowercase) 自动将值转换为小写
大写 (uppercase) 自动将值转换为大写

参数说明

参数 说明
名称[=值] 变量名和可选的初始值。可以同时声明多个变量
-a 声明索引数组变量
-A 声明关联数组(键值对)变量
-f 显示函数定义。如果指定函数名,只显示该函数
-F 只显示函数名(不显示定义)
-g 在函数内部创建全局变量(默认在函数内部创建的变量是局部的)
-i 声明整数变量
-l 将变量值转换为小写
-n 为变量设置nameref属性,使其成为另一个变量的引用
-p 显示变量的属性和值。如果指定变量名,只显示该变量
-r 声明只读变量
-t 设置变量具有trace属性(对函数有效)
-u 将变量值转换为大写
-x 将变量导出到环境,使其在子shell中可用

常用示例

示例1:显示所有变量和函数

不指定参数时显示所有变量和函数:

# 显示所有变量和函数(输出很长)
$ declare

# 显示所有变量(不包括函数)
$ declare -p

# 显示所有函数
$ declare -f

# 只显示函数名
$ declare -F

示例2:声明普通变量

声明普通变量并查看其属性:

# 声明变量
$ declare myvar="Hello World"

# 查看变量值
$ echo $myvar
Hello World

# 查看变量属性和值
$ declare -p myvar
declare -- myvar="Hello World"

# 声明多个变量
$ declare var1="test1" var2="test2"
$ echo $var1 $var2
test1 test2

示例3:声明整数变量

使用-i参数声明整数变量:

# 声明整数变量
$ declare -i num1=10 num2=20

# 自动进行整数运算
$ num3=num1+num2
$ echo $num3
30

# 尝试赋非整数值(会被转换为0)
$ declare -i intvar="hello"
$ echo $intvar
0

# 整数运算示例
$ declare -i result
$ result=5*3
$ echo $result
15

# 使用不同的进制
$ declare -i hexnum=0x10
$ echo $hexnum
16

$ declare -i octnum=010
$ echo $octnum
8

示例4:声明只读变量

使用-r参数声明只读变量:

# 声明只读变量
$ declare -r readonly_var="This is readonly"

# 查看变量
$ echo $readonly_var
This is readonly

# 尝试修改(会失败)
$ readonly_var="New value"
bash: readonly_var: readonly variable

# 尝试取消设置(会失败)
$ unset readonly_var
bash: unset: readonly_var: cannot unset: readonly variable

# 声明只读整数变量
$ declare -ir readonly_int=100
$ echo $readonly_int
100

示例5:声明数组变量

使用-a参数声明索引数组:

# 声明数组变量
$ declare -a myarray

# 赋值方法1:直接赋值
$ myarray[0]="first"
$ myarray[1]="second"
$ myarray[2]="third"

# 赋值方法2:一次性赋值
$ declare -a colors=("red" "green" "blue")

# 访问数组元素
$ echo ${colors[0]}
red
$ echo ${colors[1]}
green

# 显示所有元素
$ echo ${colors[@]}
red green blue

# 数组长度
$ echo ${#colors[@]}
3

# 查看数组声明
$ declare -p colors
declare -a colors=([0]="red" [1]="green" [2]="blue")

示例6:声明关联数组

使用-A参数声明关联数组(bash 4.0+):

# 声明关联数组(键值对)
$ declare -A person

# 赋值
$ person[name]="John"
$ person[age]=30
$ person[city]="New York"

# 访问
$ echo ${person[name]}
John
$ echo ${person[age]}
30

# 显示所有键
$ echo ${!person[@]}
name age city

# 显示所有值
$ echo ${person[@]}
John 30 New York

# 查看关联数组声明
$ declare -p person
declare -A person=([name]="John" [age]="30" [city]="New York" )

# 一次性初始化关联数组
$ declare -A fruits=([apple]="red" [banana]="yellow" [grape]="purple")
$ echo ${fruits[banana]}
yellow

示例7:导出变量到环境

使用-x参数导出变量:

# 声明并导出变量
$ declare -x MY_EXPORTED_VAR="This is exported"

# 等价于
$ export MY_EXPORTED_VAR="This is exported"

# 查看环境变量
$ env | grep MY_EXPORTED_VAR
MY_EXPORTED_VAR=This is exported

# 在子shell中测试
$ bash -c 'echo $MY_EXPORTED_VAR'
This is exported

# 取消导出(但不删除变量)
$ declare +x MY_EXPORTED_VAR
$ env | grep MY_EXPORTED_VAR
# 没有输出,变量不再是环境变量

示例8:大小写转换

使用-l-u参数自动转换大小写:

# 声明小写变量(自动转换为小写)
$ declare -l lower_var
$ lower_var="HELLO WORLD"
$ echo $lower_var
hello world

# 声明大写变量(自动转换为大写)
$ declare -u upper_var
$ upper_var="hello world"
$ echo $upper_var
HELLO WORLD

# 结合其他属性
$ declare -ilu mixed_var="123abc"
$ echo $mixed_var
123ABC  # 转换为大写,但数字不受影响

示例9:在函数中使用declare

在函数内部使用declare

# 在函数内部,默认声明的变量是局部的
function test_func() {
    declare local_var="local"
    global_var="global"  # 没有使用declare,默认是全局的
    echo "Inside function: local_var=$local_var, global_var=$global_var"
}

# 调用函数
test_func
# 输出: Inside function: local_var=local, global_var=global

# 在函数外访问
echo "Outside function: local_var=$local_var, global_var=$global_var"
# 输出: Outside function: local_var=, global_var=global
# local_var不存在,global_var存在

# 使用-g选项在函数内部创建全局变量
function create_global() {
    declare -g global_in_func="created in function"
    declare local_in_func="local in function"
}

create_global
echo $global_in_func  # 输出: created in function
echo $local_in_func   # 输出: (空)

示例10:使用nameref引用变量

使用-n参数创建变量引用(bash 4.3+):

# 创建原始变量
$ original_var="Original Value"

# 创建引用变量
$ declare -n ref_var=original_var

# 通过引用访问
$ echo $ref_var
Original Value

# 通过引用修改
$ ref_var="Modified Value"
$ echo $original_var
Modified Value  # 原始变量也被修改

# 修改原始变量
$ original_var="Changed Again"
$ echo $ref_var
Changed Again  # 引用变量也同步改变

# 引用数组
$ declare -a my_array=(one two three)
$ declare -n array_ref=my_array
$ echo ${array_ref[1]}
two
$ array_ref[1]="TWO"
$ echo ${my_array[1]}
TWO

⚠️ 注意事项

  1. 只读变量:只读变量一旦设置就不能修改或删除,只能通过关闭shell来移除
  2. 变量作用域:在函数内部使用declare创建的变量默认是局部的,除非使用-g选项
  3. bash版本:某些功能(如关联数组、nameref)需要较新版本的bash
  4. 性能影响:大量使用declare可能会影响脚本性能
  5. 可移植性:declare是bash特有,其他shell可能不支持

💡 实用技巧

  1. 调试脚本:使用declare -p查看变量状态帮助调试
  2. 类型安全:使用-i确保变量只包含整数
  3. 数据保护:使用-r保护重要变量不被意外修改
  4. 结构化数据:使用关联数组管理键值对数据
  5. 大小写规范化:使用-l-u确保数据格式一致

常见问题

Q: declare和typeset有什么区别?

A: 在bash中,declaretypeset是完全相同的命令。typeset是ksh中的命令,bash为了兼容性也提供了。

Q: 如何取消declare设置的属性?

A: 使用"+"代替"-"。例如:declare +r variable取消只读属性,declare +i variable取消整数属性。

Q: 为什么在函数内部声明的变量在外部访问不到?

A: 在函数内部使用declare声明的变量默认是局部的。要在函数内部创建全局变量,使用declare -g或直接赋值(不使用declare)。

Q: 如何查看变量的所有属性?

A: 使用declare -p 变量名可以显示变量的所有属性和当前值。

Q: declare可以用于设置环境变量吗?

A: 可以,使用declare -x将变量导出到环境,功能与export相同。

相关命令

  • typeset - 与declare相同的命令(ksh风格)
  • export - 导出变量到环境
  • readonly - 设置只读变量
  • local - 在函数内声明局部变量
  • unset - 删除变量
  • set - 设置shell选项和位置参数
  • env - 显示环境变量