You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Bash函数读取JSON文件,将含数组、对象的所有数据赋值为对应变量

实现Bash读取JSON并映射为原生变量/数组/关联数组的函数

要解决Bash无法原生处理JSON数组和对象的问题,我们可以借助jq工具(轻量且强大的JSON处理器)实现一个递归函数,将JSON结构完整映射为Bash的普通变量、索引数组和关联数组。

函数实现

json_to_bash() {
    local json_file="$1"
    # 检查jq是否安装
    if ! command -v jq &> /dev/null; then
        echo "错误:未找到jq工具,请先安装(如:apt install jq / brew install jq)" >&2
        return 1
    fi
    # 检查Bash版本(关联数组需要4.0+)
    if ((BASH_VERSINFO[0] < 4)); then
        echo "错误:Bash版本需4.0及以上,当前版本为$BASH_VERSION" >&2
        return 1
    fi

    # 通过jq生成Bash赋值语句,再用eval执行
    eval "$(jq -r '
        # 清理键名:替换非法字符为下划线
        def sanitize_key($key): $key | gsub("[^a-zA-Z0-9_]"; "_");
        # 生成普通变量赋值语句
        def emit_var($prefix; $key; $value):
            "\($prefix)\(sanitize_key($key))=\($value | @sh)";
        # 生成索引数组赋值语句
        def emit_array($prefix; $key; $array):
            "\($prefix)\(sanitize_key($key))=(" + ($array[] | @sh) + ")";
        # 生成关联数组声明及赋值语句
        def emit_assoc_array($prefix; $key; $obj):
            "declare -A \($prefix)\(sanitize_key($key));" +
            ($obj | to_entries[] |
                if .value.type == "object" or .value.type == "array" then
                    empty # 嵌套结构交给递归处理
                else
                    "\($prefix)\(sanitize_key($key))[\(sanitize_key(.key))]=\(.value | @sh)"
                end
            );
        # 递归处理嵌套结构
        def process($prefix):
            . as $in |
            if type == "object" then
                to_entries[] |
                ($prefix + sanitize_key(.key) + "_") as $new_prefix |
                if .value.type == "object" then
                    emit_assoc_array($prefix; .key; .value)
                    .value | process($new_prefix)
                elif .value.type == "array" then
                    emit_array($prefix; .key; .value)
                    .value | to_entries[] |
                    ($new_prefix + (.key | tostring) + "_") as $arr_prefix |
                    .value | process($arr_prefix)
                else
                    emit_var($prefix; .key; .value)
                end
            elif type == "array" then
                to_entries[] |
                ($prefix + (.key | tostring) + "_") as $arr_prefix |
                .value | process($arr_prefix)
            else
                empty
            end;
        # 处理顶层JSON结构
        if type == "object" then
            to_entries[] |
            if .value.type == "object" then
                emit_assoc_array(""; .key; .value)
                .value | process(sanitize_key(.key) + "_")
            elif .value.type == "array" then
                emit_array(""; .key; .value)
                .value | to_entries[] |
                (sanitize_key(.key) + "_" + (.key | tostring) + "_") as $arr_prefix |
                .value | process($arr_prefix)
            else
                emit_var(""; .key; .value)
            end
        elif type == "array" then
            emit_array(""; "json_array"; .)
            . | to_entries[] |
            ("json_array_" + (.key | tostring) + "_") as $arr_prefix |
            .value | process($arr_prefix)
        else
            emit_var(""; "json_var"; .)
        end
    ' "$json_file")"
}

使用示例

1. 准备测试JSON文件(test.json)

{
    "app_name": "MyApp",
    "version": 1.0,
    "debug_mode": true,
    "allowed_users": ["alice", "bob", "charlie"],
    "database": {
        "host": "localhost",
        "port": 5432,
        "credentials": {
            "username": "admin",
            "password": "s3cr3t!@#"
        }
    },
    "feature_flags": ["auth", {"name": "api", "enabled": false}]
}

2. 调用函数

# 加载函数(可以将函数加入~/.bashrc永久生效)
source path/to/your/function.sh
# 读取JSON文件
json_to_bash test.json

3. 访问映射后的Bash变量

# 普通变量
echo $app_name          # 输出: MyApp
echo $version           # 输出: 1.0
echo $debug_mode        # 输出: true

# 索引数组
echo "${allowed_users[@]}"  # 输出: alice bob charlie
echo "${allowed_users[1]}"  # 输出: bob

# 关联数组
echo "${database["host"]}"  # 输出: localhost
echo "${database_credentials["password"]}"  # 输出: s3cr3t!@#

# 数组中的嵌套对象(生成前缀为feature_flags_1_的变量)
echo $feature_flags_1_name    # 输出: api
echo $feature_flags_1_enabled # 输出: false

关键说明

  • 键名处理:JSON键中的特殊字符(如-、.)会被替换为下划线,确保符合Bash变量名规则。
  • 类型映射:JSON字符串/数字/布尔/null会转为Bash字符串;JSON数组转为Bash索引数组;JSON对象转为Bash关联数组。
  • 嵌套处理:递归解析嵌套的JSON对象和数组,生成带层级前缀的变量/数组,比如database.credentials转为database_credentials关联数组。
  • 安全保障:使用jq的@sh过滤器自动转义特殊字符,避免命令注入风险,但仍需确保JSON文件来源可信(因为使用了eval)。

内容的提问来源于stack exchange,提问作者Charlweed

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 19:54:53