5

I am trying to pass a variable into jq like this '.Linux.date.$var' so far I have tried quoting them by name which is working fine. But I want to use variable to call them.

I have this, which is working fine

exectime=$(date -d now);    
cp $check_exec_history $check_exec_history.tmp
    jq --arg key1 true --arg key2 "$exectime" --arg name "$name" '.Linux.script_executed.first = $key1 | .Linux.date_executed.first = $key2' $check_exec_history.tmp > $check_exec_history; 
    rm $check_exec_history.tmp;

I want to get to this, but not working:

name=first;
exectime=$(date -d now);
cp $check_exec_history $check_exec_history.tmp
jq --arg key1 true --arg key2 "$exectime" --arg name "$name" ".Linux.script_executed.$name = $key1 | .Linux.date_executed.$name = $key2" $check_exec_history.tmp > $check_exec_history; 
rm $check_exec_history.tmp;

I came this far: using this answer https://stackoverflow.com/q/40027395/9496100 But I am not sure where I am doing mistake.

name=first;
exectime=$(date -d now);    
cp $check_exec_history $check_exec_history.tmp
    jq --arg key1 true --arg key2 "$exectime" --arg name "$name" '.Linux.script_executed.name==$name = $key1 | .Linux.date_executed.name==$name = $key2' $check_exec_history.tmp > $check_exec_history; rm $check_exec_history.tmp;

2 Answers 2

6

You can use square bracket indexing on all objects in jq, so [$name] works for what you're trying:

jq --arg key1 true --arg name "$name" '.Linux.script_executed[$name] = $key1 ...' 

This use of square brackets is not very well documented in the manual, which makes it look like you can only use .[xyz], but ["x"] works anywhere that .x would have as long as it's not right at the start of an expression (that is, .a.x and .a["x"] are the same, but ["x"] is an array construction).

Note the use of single quotes above - that is so Bash won't try to interpret $name and $key1 as shell variables. You should keep the double quotes for --arg name "$name", because that really is a shell variable, and it should be quoted to make it safe to use.

2
  • Had to use -n/--null-input two work without piped input name=foobar; jq -n --arg key1 true --arg name "$name" '.Linux.script_executed[$name] = $key1'
    – eephillip
    Commented Feb 10, 2021 at 23:59
  • Square bracket help me and fix my issue. Below is sample I used in my case: RUNNER_TOKEN=$(aws secretsmanager get-secret-value --secret-id $SECRET_ID | jq '.SecretString|fromjson' | jq --arg kt $SECRET_KEY -r '.[$kt]' | tr -d '"') Commented Dec 30, 2021 at 10:58
-1

Michael Homer has the correct response. I'll post what I was aiming for in relation to op's question.

I am trying to modify a permissions graph obtained through a REST API curl call using jq to output a json file which I will PUT to the server with updates. The following is the output of the curl API query:

{
  "revision": 2,
  "groups": {
    "1": {
      "1": {
        "native": "none",
        "schemas": "none"
      },
      "2": {
        "native": "write",
        "schemas": "all"
      }
    },
    "2": {
      "1": {
        "native": "write",
        "schemas": "all"
      },
      "2": {
        "native": "write",
        "schemas": "all"
      }
    }
  }
}

As you can see it is nested. I am trying to modify this using bash variables every time a new permission set is created and when databases are created. For exmaple I'm trying to modify groups."1"."2"."native" and "schemas" also "groups."2"."2".native and "schemas" values. It's rough, but the keys are as follows groups.groupPermissionID.DatabaseID.*

In order to modify this nested graph on the fly via a bash shell script, I used Michael Homer's solution of applying [$name]. In my case I had to do this twice in a row. i.e., [$gID][$dID]. In the following setup the variables are constant but in my model they are command arguments passed to the bash shell script.

dbID="2"
pgroupID="2"

curl -X GET -H "Content-Type: application/json" -H "X-Metabase-Session: XXXXX-XXXXX-XXXXX-XXXXXXXXX" "http://localhost:9000/api/permissions/graph" | jq --arg dID "$dbID"   --arg gID "$pgroupID" -r '.groups."1"[$dID]."native" = "none" | .groups."1" [$dID]."schemas" = "none" | .groups[$gID][$dID]."native" ="none" .groups[$gID][$dID]."schemas" ="none"' > permissiongraph.json

Which produced the following updated JSON graph for me to PUT to my server:

{
  "revision": 2,
  "groups": {
    "1": {
      "1": {
        "native": "none",
        "schemas": "none"
      },
      "2": {
        "native": "none",
        "schemas": "none"
      }
    },
    "2": {
      "1": {
        "native": "write",
        "schemas": "all"
      },
      "2": {
        "native": "none",
        "schemas": "none"
      }
    }
  }
}

Michael is correct when he said this is sparsely documented. I couldn't find it anywhere in the manuals. I hope this helps someone.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .