首页 > 解决方案 > 如何在 shell 脚本中解析 JSON?

问题描述

我运行 curl 命令$(curl -i -o - --silent -X GET --cert "${CERT}" --key "${KEY}" "$some_url")并将响应保存在变量响应中。${response}如下图

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 34
Connection: keep-alive
Keep-Alive: timeout=5
X-XSS-Protection: 1; 

{"status":"running","details":"0"}

我想解析 JSON{"status":"running","details":"0"}并将“运行”和“详细信息”分配给两个不同的变量,我可以在其中打印状态和详细信息。此外,如果状态等于错误,脚本应该退出。我正在执行以下操作来完成任务 -

status1=$(echo "${response}" | awk '/^{.*}$/' | jq -r '.status')
details1=$(echo "${response}" | awk '/^{.*}$/' | jq -r '.details')
echo "Status: ${status1}"
echo "Details: ${details1}"
if [[ $status1 == 'error' ]]; then
    exit 1
fi

我不想解析 JSON 两次,而只想解析一次。因此,我想合并以下几行,但仍将状态和详细信息分配给两个单独的变量 -

status1=$(echo "${response}" | awk '/^{.*}$/' | jq -r '.status')
details1=$(echo "${response}" | awk '/^{.*}$/' | jq -r '.details')

标签: jsonbashshellshjq

解决方案


首先,停止使用-i参数 tocurl。这消除了对awk(或事后对标头的任何其他修剪)的需要。

第二:

{
  IFS= read -r -d '' status1
  IFS= read -r -d '' details1
} < <(jq -r '.status + "\u0000" + .details + "\u0000"' <<<"$response")

使用 NUL 作为分隔符的优点是它是唯一不能出现在 C 样式字符串的值中的字符(这就是 shell 变量值的存储方式)。


推荐阅读