json 在bash中解析curl响应,不使用jq

thigvfpy  于 2023-02-26  发布在  其他
关注(0)|答案(3)|浏览(199)

我试图解析一个数组,数组的子数组,在bash中从curl请求返回的json响应中。不幸的是,我不能使用jq,因为它不能安装在生产服务器上。我尝试在curl请求中使用awk或sed,但结果为空。所以我使用grep和regex,但我不能正确地迭代。

#!/bin/bash

PARAM=$1

# Run environment variables
export $(grep -v '^#' ${PWD}/.env | xargs)

# Step 1 : Get JWT Token
TOKEN=$(curl \
  --silent \
  --request POST "${URL_API}"/login \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  -d '{"username": "'${API_USERNAME}'", "password": "'${API_PWD}'" }' \
  | sed -n 's|.*"token":"\([^"]*\)".*|\1|p'
)

# Step 2 curl GET request and put it in json file
JSON_RESULT=$(curl \
  --silent \
  --output test.json \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/json' \
  --header 'Authorization: Bearer '${TOKEN}'' \
  --request GET "${URL_API}"/sites/list?value="${PARAM}" \
)

API的Json响应:

{
  "data": [
    {
      "id": 212,
      "list": [
        "value1",
        "value2",
        "value3",
        "value4"
      ],

      "createdAt": "2023-02-09T15:47:38+01:00",
      "foo": "bar",
      "foo2": "ba2r",
    }
  ],
  "metas": {
    "code": 200,
    "count": 1,
    "total": 5
  }
}

我想要"list"键的结果作为数组类型。我尝试这样做:

# Step 3 retrieve data in "list" sub-key in json
TEST=$(grep -zoP '"list":\s*\K[^\s]*(?=\s*,)' test.json)
echo ${TEST}

显示:

> scripts/test.sh: line 35: warning: command substitution: ignored null byte in input
["value1","value2","value3","value4"]

如何将其解析为数组以执行以下操作:

# step 4 iterate
IFS=',' read -ra ADDR <<< "$TEST"
for i in "${ADDR[@]}"; do
  echo $i
done

yh2wf1be

yh2wf1be1#

对于sed,使用文件作为输入-

$: sed -nE 'H; ${x; s/[ \n]+//g; s/^.*"list":\[/\[/;s/\].*/]/;p;}' file
["value1","value2","value3","value4"]

即使文件中没有嵌入空格或换行符,这也能正常工作。
接线盒:
-nE只是堆叠-n-E
-n表示n o输出,除非显式请求。-E使用E扩展模式匹配,因此您不必将方括号用反斜杠括起来。
在实际命令列表中,
H;将输入的每一行堆叠到H旧缓冲器上。
除最后一行外,不对任何行执行其他命令。
${...}表示“在最后一行,执行以下命令...”
x e x更改输入缓冲区和H旧缓冲区,将您保存的所有行放入工作区。
s/[ \n]+//g将用s替换空格和换行符,g在缓冲区中不存在任何内容,将所有内容堆叠成一个长行,并删除所有空格。
s/^.*"list":\[/\[/表示只使用[替换从开头(^)到文字list:[的所有内容。
s/\].*/]/表示只使用]替换从剩余的第一个[开始的所有内容。
pp rint工作区缓冲区,此时它应该就是您所要求的数据。

z5btuh9x

z5btuh9x2#

帮助@Paul Hodges解决方案,我找到了添加此link的方法
因此:

# Paul Hodges solution above
LIST=$(sed -nE 'H; ${x; s/[ \n]+//g; s/^.*"list":\[/\[/;s/\].*/]/;p;}' test.json)

# Link
borkstring=$(echo $LIST | sed -e 's/\[//g' -e 's/\]//g' -e 's/\, //g')
IFS=',' read -ra arr <<< "$borkstring"
for i in ${arr[@]}; do
    VALUE=${i//\"}
    echo "value: "$VALUE
done

结果:

value: value1
value: value2
value: value3
value: value4

这是确定的。也许我的代码可以美化更多了:)

idfiyjo8

idfiyjo83#

使用while read构造:

while read -r line; do

    [[ $line =~ list ]] && { add_to__list=true; continue; }
    [[ $add_to__list ]] && {
        [[ $line =~ \], ]] && break
        list+=( "${line//[\",]}" )
    }

done < json.file

echo "${list[@]}"

结果:

value1 value2 value3 value4

相关问题