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

Makefile中如何将命令输出赋值给变量并遍历对象数组

解决Makefile中遍历JSON数组访问字段的错误问题

问题场景

在Makefile中执行az graph query命令获取JSON格式结果,尝试将结果赋值给变量后遍历数组对象访问status字段时,出现错误:

/bin/bash: line 4: ${result.status}: bad substitution
make: *** [Makefile:23: check] Error 1

原Makefile代码:

QUERY := "securityresources | where type == 'microsoft.security/assessments' | summarize by assessmentKey=name | join kind=inner ( securityresources | where type == 'microsoft.security/assessments/subassessments' | extend assessmentKey = extract('.*assessments/(.+?)/.*',1, id) ) on assessmentKey | where properties.additionalData.assessedResourceType == 'ContainerRegistryVulnerability' | extend status = properties.status.code | extend severity = properties.status.severity"

.ONESHELL:
check:
    # az graph query -q ${QUERY}
    results="`az graph query -q ${QUERY}`"
    @for result in $$results.data;
    do
        echo "$${result.status}"
    done

az graph query返回的JSON示例:

{ "count": 10,
  "data" : [{"status":"healthy", "abc":"123"},
            {"status":"unhealthy", "abc":"322"},
            {"status":"healthy", "abc":"432"}
           ]
}

错误原因

  1. Bash本身不支持直接解析JSON结构,results变量存储的是整个JSON字符串,$$results.data无法提取数组内容,遍历的是字符串的字符而非JSON对象。
  2. ${result.status}是JSON对象的属性访问语法,Bash不识别这种变量替换格式,因此报"bad substitution"错误。

解决方案

使用jq工具(专门的JSON处理工具)来解析和提取JSON数据,避免在Bash中直接处理JSON结构。以下是两种实现方式:

方式1:直接提取并输出指定字段

如果只需要输出status字段,可直接用jq一步完成:

QUERY := "securityresources | where type == 'microsoft.security/assessments' | summarize by assessmentKey=name | join kind=inner ( securityresources | where type == 'microsoft.security/assessments/subassessments' | extend assessmentKey = extract('.*assessments/(.+?)/.*',1, id) ) on assessmentKey | where properties.additionalData.assessedResourceType == 'ContainerRegistryVulnerability' | extend status = properties.status.code | extend severity = properties.status.severity"

.ONESHELL:
check:
    # 直接用jq提取data数组中每个对象的status字段并输出
    @az graph query -q ${QUERY} | jq -r '.data[] | .status'

方式2:遍历JSON对象做复杂处理

如果需要对每个JSON对象执行更多操作,可先用jq将数组元素转为单行字符串,再在Bash中遍历处理:

QUERY := "securityresources | where type == 'microsoft.security/assessments' | summarize by assessmentKey=name | join kind=inner ( securityresources | where type == 'microsoft.security/assessments/subassessments' | extend assessmentKey = extract('.*assessments/(.+?)/.*',1, id) ) on assessmentKey | where properties.additionalData.assessedResourceType == 'ContainerRegistryVulnerability' | extend status = properties.status.code | extend severity = properties.status.severity"

.ONESHELL:
check:
    @az graph query -q ${QUERY} | jq -c '.data[]' | while read -r result; do
        # 用jq从单个JSON对象中提取字段
        status=$(echo "$$result" | jq -r '.status')
        abc=$(echo "$$result" | jq -r '.abc')
        echo "状态: $$status, ABC值: $$abc"
    done

关键说明

  • jq工具:需提前安装(可通过apt install jq或brew install jq完成),它能高效处理JSON的解析、过滤和转换。
  • Makefile变量转义:在Makefile的shell命令中,所有$需要写成$$,避免被Make解析为Make变量。
  • .ONESHELL:确保整个check目标的命令在同一个shell进程中执行,避免变量跨shell失效(多步shell操作时必备)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 12:55:25