JQ parsing strings with “-”

2019-07-16 02:44发布

My JSON:

{
    "projects": {
        "api-client": {
            "status": "false",
            "when": "19-01-2016 12:54:47"
        },
        "api-admin": {
            "status": "false",
            "when": "19-01-2016 12:54:47"
        },
        "myweb": {
            "status": "false",
            "when": "19-01-2016 12:54:47"
        }
    }
}

Script:

JQ=$(which jq)
CACHE='cache.json'
PROJECT=("api-client" "api-admin" "myweb")
for PROJECT in ${PROJECTS[*]}; do
    if [[ $(${JQ} -r ".projects.\"${PROJECT}\"" ${CACHE}) != null ]]; then
        if [[ $(${JQ} -r ".projects.\"${PROJECT}\".status" ${CACHE}) == true ]]; then
            local PROJECTDATE=$(${JQ} -r ".projects.\"${PROJECT}\".when" ${CACHE})
            local STATUS="${COLOR_GREEN}Installed${CLEAR} on ${COLOR_YELLOW}${PROJECTDATE}${CLEAR}"
        else
            local STATUS="${COLOR_RED}Not installed${CLEAR}"
        fi
        echo -e "${CLEAR}    - ${COLOR_CYAN}${PROJECT}${CLEAR} => ${STATUS}"
    fi
done

Error: error: syntax error, unexpected QQSTRING_START, expecting IDENT .projects."api-client" ^ 1 compile error error: syntax error, unexpected QQSTRING_START, expecting IDENT .projects."api-client".status ^ 1 compile error - api-client => Not installed

Can someone please help debug my script?

标签: json shell jq
1条回答
beautiful°
2楼-- · 2019-07-16 03:23

First of all, .foo.bar is just shorthand syntax for .["foo"]["bar"]. Use the latter for non-alphanumeric values such as api-client.

Secondly, you should never compose jq scripts by interpolating shell variables into them. Instead, pass values to them using --arg. That is, instead of doing this:

${JQ} -r ".projects.\"${PROJECT}\"" ${CACHE}

You should probably be doing this:

${JQ} --arg project "$PROJECT" -r '.projects[$project]' ${CACHE}

Note the single quotes around the jq program: $project is syntax for a jq variable, like in Perl or PHP; it is not being interpolated by the shell. Always use single quotes around your jq programs.

Thirdly, you can use -e so that the status code is 0 on truthy values. Instead of this:

if [[ $(${JQ} -r ".projects.\"${PROJECT}\"" ${CACHE}) != null ]]; then

You can just do this:

if ${JQ} --arg project "$PROJECT" -e -r '.projects[$project]' ${CACHE}; then

Similarly, you can remove the comparison to true in the same manner.

查看更多
登录 后发表回答