Search code examples
shellcurljqgithub-api

Json parsing in shell script


I am trying to automate github repo creation. Below is my code:

pushtogithub() {
        git init
        git config user.name "user name"
        git config user.email "user email"
        git add .
        git commit -m "Initial commit"
        content=$(curl -s -u githubusername:githubaccesstoken https://api.github.com/user/repos -d '{"name":"$1", "private":true}')
        repo=$(jq -r '.ssh_url' <<< "${content}" )
        echo $repo created
        git remote add origin [email protected]:githubusername/$repo.git
        git push -u origin master
}

My github repo is always creating with -1 name.

What I am doing wrong here?


Solution

  • Replace:

    curl ... -d '{"name":"$1", "private":true}'
    

    ...with:

    curl ... -d "$(jq -n --arg name "$1" '{"name": $name, "private": true}')"
    

    That is to say: Nothing was wrong with how you were using jq to parse JSON; the problem is that you were trying to create JSON without using jq.


    The simple-but-wrong way to try to fix this, by the way, would have been to change your quoting type:

    #### DO NOT DO THIS
    curl ... -d '{"name": "'"$1"'", "private": true}'
    

    ...or...

    ### DO NOT DO THIS EITHER
    curl ... -d "{\"name\":\"$1\", \"private\":true}"
    

    In the first example, we have everything except the $1 surrounded in single quotes; but then end those single-quotes before your expansion, switch to a double-quoted context, expand $1 there, and switch back.

    In the second example, we just put the whole thing in double quotes, escaping the ones intended to be literal rather than syntactic.

    Either approach, however, is wrong; try looking at what it does when your name is Foo "The Leet" Bar -- the literal quotes get conflated with JSON quotes, making the generated JSON invalid, unless you use a tool (like jq) that knows how to escape them.