Linux declare 命令详解与示例

declare 是 Bash shell 内置命令,用于声明变量和设置变量的属性。它是 Bash 编程中非常强大的工具。

基本语法

declare [选项] [变量名[=值]]

常用选项

选项 含义 示例
-a 声明数组 declare -a arr
-A 声明关联数组 declare -A dict
-i 声明整数变量 declare -i num
-r 声明只读变量 declare -r PI=3.14
-x 声明环境变量 declare -x PATH
-l 变量值转换为小写 declare -l lower
-u 变量值转换为大写 declare -u upper
-n 声明变量引用 declare -n ref=var
-g 在函数中声明全局变量 declare -g global_var
-p 显示变量属性和值 declare -p var

详细示例

1. 声明数组 (-a)

# 声明空数组
declare -a fruits

# 赋值方式1:逐个赋值
fruits[0]="apple"
fruits[1]="banana"
fruits[2]="orange"

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

# 赋值方式3:使用 += 追加
declare -a numbers=()
numbers+=(1)
numbers+=(2 3)

# 访问数组元素
echo ${fruits[0]}      # apple
echo ${colors[@]}      # 所有元素
echo ${#colors[@]}     # 数组长度: 3

# 遍历数组
for fruit in "${fruits[@]}"; do
    echo "水果: $fruit"
done

# 显示数组声明
declare -p fruits
# 输出: declare -a fruits=([0]="apple" [1]="banana" [2]="orange")

2. 声明关联数组 (-A)

注意:需要 Bash 4.0+

# 声明关联数组
declare -A person

# 赋值
person["name"]="张三"
person["age"]=25
person["city"]="北京"

# 访问
echo "姓名: ${person["name"]}"
echo "年龄: ${person["age"]}"

# 遍历所有键
for key in "${!person[@]}"; do
    echo "$key: ${person[$key]}"
done

# 示例2:学生成绩
declare -A grades=(
    ["math"]=90
    ["english"]=85
    ["history"]=88
)

# 计算平均分
total=0
count=0
for subject in "${!grades[@]}"; do
    total=$((total + ${grades[$subject]}))
    count=$((count + 1))
done
average=$((total / count))
echo "平均分: $average"

3. 声明整数变量 (-i)

# 声明整数变量
declare -i num1 num2 result

# 自动进行整数运算
num1=10
num2=3
result=num1+num2
echo "结果: $result"  # 13

# 注意:非数字会被转换为0
declare -i number
number="hello"
echo $number  # 0

# 支持不同进制
declare -i binary=2#1010    # 二进制: 10
declare -i octal=8#12       # 八进制: 10
declare -i hex=16#A         # 十六进制: 10
echo "二进制 1010 = $binary"
echo "八进制 12 = $octal"
echo "十六进制 A = $hex"

# 使用 $(( )) 进行复杂运算
declare -i x=5 y=3
declare -i z=$(( (x + y) * 2 ))
echo "z = $z"  # 16

4. 声明只读变量 (-r)

# 声明只读变量(常量)
declare -r PI=3.14159
declare -r COMPANY_NAME="ABC科技有限公司"
declare -r -i MAX_USERS=100

echo "π = $PI"
echo "公司: $COMPANY_NAME"

# 尝试修改会报错
# PI=3.14  # bash: PI: readonly variable

# 也可以在声明后设为只读
declare config_file="/etc/app.conf"
declare -r config_file  # 现在变为只读

5. 声明环境变量 (-x)

# 声明为环境变量(在当前shell和子进程中可用)
declare -x DATABASE_URL="mysql://user:pass@localhost/db"
declare -x -i DEBUG_LEVEL=1

# 等同于 export,但可以同时设置属性
export APP_ENV="production"  # 传统方式
declare -x APP_ENV="production"  # 使用declare

# 显示所有环境变量
declare -x

# 取消导出
declare +x VARIABLE_NAME

6. 大小写转换 (-l-u)

# 自动转换为小写
declare -l lowercase
lowercase="HELLO World"
echo $lowercase  # hello world

# 自动转换为大写
declare -l uppercase  # 注意:这里用小写l是错误的,应该用-u
declare -u uppercase  # 正确
uppercase="hello World"
echo $uppercase  # HELLO WORLD

# 实际应用:规范化用户输入
declare -l username
read -p "输入用户名: " username
echo "标准化用户名: $username"

7. 变量引用 (-n)

# 创建变量引用(类似指针)
var="原始值"
declare -n ref=var

echo "var = $var"      # 原始值
echo "ref = $ref"      # 原始值

# 通过引用修改变量
ref="新值"
echo "var = $var"      # 新值
echo "ref = $ref"      # 新值

# 实际应用:函数中操作调用者的变量
function increment() {
    declare -n ref=$1
    ref=$((ref + 1))
}

count=10
echo "之前: count = $count"
increment count
echo "之后: count = $count"  # 11

8. 在函数中声明全局变量 (-g)

# 没有 -g 选项,变量默认是局部的
function set_local() {
    local_var="函数内部"
    echo "局部变量: $local_var"
}

function set_global() {
    declare -g global_var="全局可访问"
    echo "全局变量: $global_var"
}

set_local
echo "外部访问局部变量: ${local_var:-未定义}"  # 未定义

set_global
echo "外部访问全局变量: $global_var"  # 全局可访问

9. 查看变量属性 (-p)

# 创建各种变量
declare -i age=25
declare -r name="张三"
declare -a hobbies=("阅读" "运动" "音乐")
declare -A info=(["email"]="zhang@example.com" ["phone"]="13800138000")

# 查看变量声明
declare -p age
# 输出: declare -i age="25"

declare -p name
# 输出: declare -r name="张三"

declare -p hobbies
# 输出: declare -a hobbies=([0]="阅读" [1]="运动" [2]="音乐")

declare -p info
# 输出: declare -A info=([phone]="13800138000" [email]="zhang@example.com" )

# 查看所有变量
declare -p

# 查看特定类型的变量
declare -p | grep "declare -a"  # 所有数组
declare -p | grep "declare -i"  # 所有整数

综合示例

示例1:配置管理系统

#!/bin/bash
# config_manager.sh

# 声明只读配置
declare -r -i MAX_LOG_SIZE=10485760  # 10MB
declare -r DEFAULT_USER="guest"
declare -r CONFIG_DIR="/etc/myapp"

# 声明全局配置数组
declare -g -A config=(
    ["debug"]="false"
    ["log_level"]="INFO"
    ["timeout"]=30
)

# 声明本地数组
declare -a users=("admin" "user1" "user2")

function show_config() {
    echo "=== 配置信息 ==="
    echo "最大日志大小: $MAX_LOG_SIZE bytes"
    echo "默认用户: $DEFAULT_USER"
    echo "配置目录: $CONFIG_DIR"
    
    echo -e "\n动态配置:"
    for key in "${!config[@]}"; do
        printf "  %-10s: %s\n" "$key" "${config[$key]}"
    done
    
    echo -e "\n用户列表:"
    printf "  %s\n" "${users[@]}"
}

function update_config() {
    declare -n key=$1
    declare value=$2
    
    if [[ -v config[$key] ]]; then
        config[$key]=$value
        echo "配置已更新: $key=$value"
    else
        echo "错误: 未知配置项 $key"
    fi
}

# 使用示例
show_config
update_config "timeout" 60
update_config "log_level" "DEBUG"
show_config

示例2:数学计算器

#!/bin/bash
# calculator.sh

declare -i result
declare -a history=()

function calculate() {
    declare -i a=$1
    declare operation=$2
    declare -i b=$3
    
    case $operation in
        +) result=a+b ;;
        -) result=a-b ;;
        *) result=a*b ;;
        /) 
            if (( b != 0 )); then
                result=a/b
            else
                echo "错误: 除数不能为0"
                return 1
            fi
            ;;
        %)
            if (( b != 0 )); then
                result=a%b
            else
                echo "错误: 除数不能为0"
                return 1
            fi
            ;;
        *) 
            echo "错误: 不支持的操作 $operation"
            return 1
            ;;
    esac
    
    # 记录历史
    history+=("$a $operation $b = $result")
    return 0
}

# 使用示例
calculate 10 + 5
echo "10 + 5 = $result"

calculate 20 / 4
echo "20 / 4 = $result"

calculate 7 % 3
echo "7 % 3 = $result"

echo -e "\n计算历史:"
printf "%s\n" "${history[@]}"

示例3:用户管理系统

#!/bin/bash
# user_manager.sh

# 声明关联数组存储用户信息
declare -A users

# 用户操作函数
function add_user() {
    declare username=$1
    declare email=$2
    declare -i age=$3
    
    users["$username,email"]=$email
    users["$username,age"]=$age
    users["$username,active"]=1
    
    echo "用户 $username 添加成功"
}

function deactivate_user() {
    declare username=$1
    
    if [[ -v users["$username,active"] ]]; then
        users["$username,active"]=0
        echo "用户 $username 已停用"
    else
        echo "错误: 用户 $username 不存在"
    fi
}

function show_user() {
    declare username=$1
    
    echo "=== 用户信息 ==="
    echo "用户名: $username"
    echo "邮箱: ${users["$username,email"]:-未设置}"
    echo "年龄: ${users["$username,age"]:-未设置}"
    echo "状态: $([ "${users["$username,active"]:-0}" -eq 1 ] && echo "活跃" || echo "停用")"
}

# 使用示例
add_user "alice" "alice@example.com" 25
add_user "bob" "bob@example.com" 30

show_user "alice"
deactivate_user "bob"
show_user "bob"

实用技巧

1. 批量声明变量

declare -i a b c
declare -r constant1="val1" constant2="val2"
declare -a arr1 arr2

2. 移除变量属性

declare +i variable  # 移除整数属性
declare +r variable  # 移除只读属性(如果可能)
declare +a array     # 移除数组属性

3. 检查变量是否存在

if declare -p variable_name &>/dev/null; then
    echo "变量存在"
else
    echo "变量不存在"
fi

4. 从文件加载变量声明

# config.vars
declare -r API_KEY="123456"
declare -i TIMEOUT=30
declare -a HOSTS=("server1" "server2")

# 加载
source config.vars

5. 安全的变量操作

# 使用小写变量名,避免覆盖环境变量
declare -l local_var

# 使用前缀避免冲突
declare -r MYAPP_CONFIG_DIR="/etc/myapp"

注意事项

  1. 作用域规则

    • 在函数内默认声明局部变量
    • 使用 -g 声明全局变量
    • 使用 local 命令声明局部变量(只能用于函数内)
  2. 只读变量不可修改

    declare -r var="value"
    # var="new"  # 会报错
    
  3. 整数变量的特殊性

    declare -i num
    num="10 + 20"  # 会被计算为30
    
  4. Bash版本兼容性

    • 关联数组 (-A) 需要 Bash 4.0+
    • 大小写转换 (-l-u) 需要 Bash 4.0+
  5. 性能考虑

    • declare 是内置命令,执行速度快
    • 合理使用变量属性可以提高脚本性能

declare 是编写健壮、可维护的 Bash 脚本的重要工具。通过合理使用变量属性,可以提高代码的清晰度和安全性。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐