简体   繁体   English

如何在shell脚本中解析JSON?

[英]How to parse JSON in shell script?

I run the curl command $(curl -i -o - --silent -X GET --cert "${CERT}" --key "${KEY}" "$some_url") and save the response in the variable response. 我运行curl命令$(curl -i -o - --silent -X GET --cert "${CERT}" --key "${KEY}" "$some_url")并将响应保存在变量响应中。 ${response} is as shown below $ {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"}

I want to parse the JSON {"status":"running","details":"0"} and assign 'running' and 'details' to two different variables where I can print status and details both. 我想解析JSON {"status":"running","details":"0"}并将'running'和'details'分配给两个不同的变量,我可以在这两个变量中打印状态和详细信息。 Also if the status is equal to error, the script should exit. 此外,如果状态等于错误,则脚本应退出。 I am doing the following to achieve the task - 我正在做以下任务来完成任务 -

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

Instead of parsing the JSON twice, I want to do it only once. 我想要只做一次,而不是两次解析JSON。 Hence I want to combine the following lines but still assign the status and details to two separate variables - 因此,我想结合以下几行,但仍然将状态和细节分配给两个单独的变量 -

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

First, stop using the -i argument to curl . 首先, 停止使用-i参数进行curl That takes away the need for awk (or any other pruning of the header after-the-fact). 这消除了对awk的需求(或事后的任何其他头部修剪)。

Second: 第二:

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

The advantage of using a NUL as a delimiter is that it's the sole character that can't be present in the value of a C-style string (which is how shell variables' values are stored). 使用NUL作为分隔符的优点是它是唯一的字符,不能出现在C风格字符串的值中(这是shell变量值的存储方式)。

You can use a construction like: 你可以使用如下结构:

read status1 details1 < <(jq -r '.status + " " + .details' <<< "${response}")

You use read to assign the different inputs to two variables (or an array, if you want), and use jq to print the data you need separated by whitespace. 您可以使用read将不同的输入分配给两个变量(或数组,如果需要),并使用jq打印您需要用空格分隔的数据。

As Benjamin already suggested, only retrieving the json is a better way to go. 正如本杰明已经建议的那样,只检索json是一种更好的方法。 Poshi's solution is solid. Poshi的解决方案很扎实。

However, if you're looking for the most compact to do this, no need to save the response as a variable if the only thing your're going to do with it is extract other variables from it on a one time basis. 但是,如果您正在寻找最紧凑的方法,那么无需将响应保存为变量,如果您要做的唯一事情就是一次性从中提取其他变量。 Just pipe curl directly into: 只需将卷曲直接卷入:

curl "whatever" | jq -r '[.status, .details] |@tsv' 

or 要么

curl "whatever" | jq -r '[.status, .details] |join("\t")'

and you'll get your values fielded for you. 并且你会得到你的价值观。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM